📄 xil_cache.c
字号:
while (adr < end) {#ifdef __GNUC__ /* Invalidate L1 I-cache line */ __asm__ __volatile__("mcr " \ XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (adr));#else { volatile register unsigned int Reg __asm(XREG_CP15_INVAL_IC_LINE_MVA_POU); Reg = adr; }#endif /* Invalidate L2 cache line */ *L2CCOffset = adr; adr += cacheline; } } /* Wait for L1 and L2 invalidate to complete */ dsb(); do { L2CCReg = Xil_In32(XPS_L2CC_BASEADDR + XPS_L2CC_CACHE_SYNC_OFFSET); } while (L2CCReg != 0);}/****************************************************************************** Enable the level 1 Data cache.** @param None.** @return None.** @note None.*****************************************************************************/void Xil_L1DCacheEnable(void){ register unsigned int CtrlReg; /* enable caches only if they are disabled */#ifdef __GNUC__ CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);#else { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL); CtrlReg = Reg; }#endif if (CtrlReg & XREG_CP15_CONTROL_C_BIT) { 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);}/****************************************************************************** Disable the level 1 Data cache.** @param None.** @return None.** @note None.*****************************************************************************/void Xil_L1DCacheDisable(void){ register unsigned int CtrlReg; /* clean and invalidate the Data cache */ Xil_L1DCacheFlush();#ifdef __GNUC__ /* disable the Data cache */ CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);#else { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL); CtrlReg = Reg; }#endif CtrlReg &= ~(XREG_CP15_CONTROL_C_BIT); mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);}/****************************************************************************** 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 unsigned int CsidReg, C7Reg; unsigned int CacheSize, LineSize, NumWays; unsigned int Way, WayIndex, Set, SetIndex, NumSet; /* Select cache level 0 and D cache in CSSR */ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); isb();#ifdef __GNUC__ CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);#else { volatile register unsigned int Reg __asm(XREG_CP15_CACHE_SIZE_ID); CsidReg = Reg; }#endif /* Determine Cache Size */ CacheSize = (CsidReg >> 13) & 0x1FF; CacheSize +=1; CacheSize *=128; /* to get number of bytes */ /* Number of Ways */ NumWays = (CsidReg & 0x3ff) >> 3; NumWays += 1; /* Get the cacheline size, way size, index size from csidr */ LineSize = (CsidReg & 0x07) + 4; NumSet = CacheSize/NumWays; NumSet /= (1 << LineSize); Way = 0UL; Set = 0UL; /* Invalidate all the cachelines */ for (WayIndex =0; WayIndex < NumWays; WayIndex++) { for (SetIndex =0; SetIndex < NumSet; SetIndex++) { C7Reg = Way | Set;#ifdef __GNUC__ /* Invalidate by Set/Way */ __asm__ __volatile__("mcr " \ XREG_CP15_INVAL_DC_LINE_SW :: "r" (C7Reg));#else //mtcp(XREG_CP15_INVAL_DC_LINE_SW, C7Reg); { volatile register unsigned int Reg __asm(XREG_CP15_INVAL_DC_LINE_SW); Reg = C7Reg; }#endif Set += (1 << LineSize); } Way += 0x40000000; } /* Wait for L1 invalidate to complete */ dsb();}/****************************************************************************** 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 Address to be flushed.** @return None.** @note The bottom 5 bits are set to 0, forced by architecture.*****************************************************************************/void Xil_L1DCacheInvalidateLine(unsigned int adr){ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); /* Wait for L1 invalidate to complete */ dsb();}/****************************************************************************** Invalidate the level 1 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 Start address of range to be invalidated.* @param Length of range to be invalidated in bytes.** @return None.** @note None.*****************************************************************************/void Xil_L1DCacheInvalidateRange(unsigned int adr, unsigned len){ const unsigned cacheline = 32; unsigned int end; if (len != 0) { /* Back the starting address up to the start of a cache line * perform cache operations until adr+len */ end = adr + len; adr = adr & ~(cacheline - 1); /* Select cache L0 D-cache in CSSR */ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); while (adr < end) {#ifdef __GNUC__ __asm__ __volatile__("mcr " \ XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (adr));#else //mtcp(XREG_CP15_INVAL_DC_LINE_MVA_POC, adr); { volatile register unsigned int Reg __asm(XREG_CP15_INVAL_DC_LINE_MVA_POC); Reg = adr; }#endif adr += cacheline; } } /* Wait for L1 invalidate to complete */ dsb();}/****************************************************************************** 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 unsigned int CsidReg, C7Reg; unsigned int CacheSize, LineSize, NumWays; unsigned int Way, WayIndex, Set, SetIndex, NumSet; /* Select cache level 0 and D cache in CSSR */ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); isb();#ifdef __GNUC__ CsidReg = mfcp(XREG_CP15_CACHE_SIZE_ID);#else { volatile register unsigned int Reg __asm(XREG_CP15_CACHE_SIZE_ID); CsidReg = Reg; }#endif /* Determine Cache Size */ CacheSize = (CsidReg >> 13) & 0x1FF; CacheSize +=1; CacheSize *=128; /* to get number of bytes */ /* Number of Ways */ NumWays = (CsidReg & 0x3ff) >> 3; NumWays += 1; /* Get the cacheline size, way size, index size from csidr */ LineSize = (CsidReg & 0x07) + 4; NumSet = CacheSize/NumWays; NumSet /= (1 << LineSize); Way = 0UL; Set = 0UL; /* Invalidate all the cachelines */ for (WayIndex =0; WayIndex < NumWays; WayIndex++) { for (SetIndex =0; SetIndex < NumSet; SetIndex++) { C7Reg = Way | Set; /* Flush by Set/Way */#ifdef __GNUC__ __asm__ __volatile__("mcr " \ XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (C7Reg));#else { volatile register unsigned int Reg __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_SW); Reg = C7Reg; }#endif Set += (1 << LineSize); } Way += 0x40000000; } /* Wait for L1 flush to complete */ dsb();}/****************************************************************************** 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 Address to be flushed.** @return None.** @note The bottom 5 bits are set to 0, forced by architecture.*****************************************************************************/void Xil_L1DCacheFlushLine(unsigned int adr){ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F))); /* Wait for L1 flush to complete */ dsb();}/***************************************************************************** Flush the level 1 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 Start address of range to be flushed.* @param Length of range to be flushed in bytes.** @return None.** @note None.*****************************************************************************/void Xil_L1DCacheFlushRange(unsigned int adr, unsigned len){ const unsigned cacheline = 32; unsigned int end; if (len != 0) { /* Back the starting address up to the start of a cache line * perform cache operations until adr+len */ end = adr + len; adr = adr & ~(cacheline - 1); /* Select cache L0 D-cache in CSSR */ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); while (adr < end) {#ifdef __GNUC__ __asm__ __volatile__("mcr " \ XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (adr));#else //mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, adr); { volatile register unsigned int Reg __asm(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC); Reg = adr; }#endif adr += cacheline; } } /* Wait for L1 flush to complete */ dsb();}/****************************************************************************** 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(unsigned int adr){ mtcp(XREG_CP15_CACHE_SIZE_SEL, 0); mtcp(XREG_CP15_CLEAN_DC_LINE_MVA_POC, (adr & (~0x1F))); /* Wait for L1 store to complete */ dsb();}/****************************************************************************** Enable the level 1 instruction cache.** @param None.** @return None.** @note None.*****************************************************************************/void Xil_L1ICacheEnable(void){ register unsigned int CtrlReg; /* enable caches only if they are disabled */#ifdef __GNUC__ CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);#else { volatile register unsigned int Reg __asm(XREG_CP15_SYS_CONTROL); CtrlReg = Reg; }#endif if (CtrlReg & XREG_CP15_CONTROL_I_BIT) { return; } /* invalidate the instruction cache */ mtcp(XREG_CP15_INVAL_IC_POU, 0); /* enable the instruction cache */ CtrlReg |= (XREG_CP15_CONTROL_I_BIT); mtcp(XREG_CP15_SYS_CONTROL, CtrlReg);}/*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -