📄 xdmaps.c
字号:
/******************************************************************************* (c) Copyright 2009-2012 Xilinx, Inc. All rights reserved.** This file contains confidential and proprietary information of Xilinx, Inc.* and is protected under U.S. and international copyright and other* intellectual property laws.** DISCLAIMER* This disclaimer is not a license and does not grant any rights to the* materials distributed herewith. Except as otherwise provided in a valid* license issued to you by Xilinx, and to the maximum extent permitted by* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;* and (2) Xilinx shall not be liable (whether in contract or tort, including* negligence, or under any other theory of liability) for any loss or damage* of any kind or nature related to, arising under or in connection with these* materials, including for any direct, or any indirect, special, incidental,* or consequential loss or damage (including loss of data, profits, goodwill,* or any type of loss or damage suffered as a result of any action brought by* a third party) even if such damage or loss was reasonably foreseeable or* Xilinx had been advised of the possibility of the same.** CRITICAL APPLICATIONS* Xilinx products are not designed or intended to be fail-safe, or for use in* any application requiring fail-safe performance, such as life-support or* safety devices or systems, Class III medical devices, nuclear facilities,* applications related to the deployment of airbags, or any other applications* that could lead to death, personal injury, or severe property or* environmental damage (individually and collectively, "Critical* Applications"). Customer assumes the sole risk and liability of any use of* Xilinx products in Critical Applications, subject only to applicable laws* and regulations governing limitations on product liability.** THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE* AT ALL TIMES.******************************************************************************//****************************************************************************//**** @file xdmaps.c** This file contains the implementation of the interface functions for XDmaPs* driver. Refer to the header file xdmaps.h for more detailed information.** <pre>* 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* </pre>******************************************************************************//***************************** Include Files ********************************/#include <string.h>#include "xstatus.h"#include "xdmaps.h"#include "xil_io.h"#include "xil_cache.h"#include "xil_printf.h"// #define XDMAPS_DEBUG#undef PDBG#ifdef XDMAPS_DEBUG# define PDBG(fmt, args...) xil_printf(fmt, ## args)#else# define PDBG(fmt, args...)#endif/************************** 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; PDBG("inside Fault ISR dev %d\r\n", InstPtr->Config.DeviceId); 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)) { PDBG("xdmaps_fault_isr: channel %d device %d\n", Chan, DevId); FaultType = XDmaPs_ReadReg(BaseAddr, XDmaPs_FTCn_OFFSET(Chan)); Pc = XDmaPs_ReadReg(BaseAddr, XDmaPs_CPCn_OFFSET(Chan)); PDBG("xdmaps_fault_isr: fault type %#x Pc %#x\n", FaultType, Pc); /* kill the channel thread */ PDBG("xdmaps_fault_isr: " "killing channel %d for device %d\n", Chan, InstPtr->Config.DeviceId); /* 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.******************************************************************************/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;}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******************************************************************************/inline int XDmaPs_Instr_DMAGO(char *DmaProg, unsigned int Cn, u32 Imm, unsigned int Ns){ PDBG("entering XDmaPs_Instr_DMAGO(%x, %d, %x, %d)\r\n", (unsigned int)DmaProg, Cn, Imm, 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.******************************************************************************/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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -