SylixOS中的动态内存分配【14】--- cache API中的非缓存内存分配接口实现原理
生活随笔
收集整理的這篇文章主要介紹了
SylixOS中的动态内存分配【14】--- cache API中的非缓存内存分配接口实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實現原理
cache API中的非緩存內存分配接口是通過內核堆或arch API接口實現的。
- 如果CPU沒有cache則cache API應該通過宏配置去掉,即使沒有去掉實際也會變成內核堆接口的調用。
- 如果系統沒有DMA區,或arch層沒有提供CACHEOP_pfuncDmaMalloc回調,則內存的分配與釋放也是通過內核堆接口實現的,但cache同步接口是有效的,也是驅動層需要調用的。
- 如果arch層提供了CACHEOP_pfuncDmaMalloc回調,則通過回調函數實現內存的分配與釋放,此時cache同步接口實際為空,也無需驅動層調用。
- 如果處理器的cache是一致性的,則從DATA區配內存,否則從DMA區分配內存。
arch層中CACHEOP_pfuncDmaMalloc回調函數的實現一般是API_VmmDmaAllocAlignWithFlags函數實現的,即使用DMA區內存進行分配與釋放。
實現源碼
內核實現源碼
/********************************************************************************************************* ** 函數名稱: API_CacheDmaMalloc ** 功能描述: 開辟一塊非緩沖的內存 ** 輸 入 : ** stBytes 長度 ** 輸 出 : 開辟的空間首地址 *********************************************************************************************************/ PVOID API_CacheDmaMalloc (size_t stBytes) {return ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(__KHEAP_ALLOC_ALIGN(stBytes, LW_CFG_CPU_ARCH_CACHE_LINE)) :(_G_cacheopLib.CACHEOP_pfuncDmaMalloc(stBytes))); } /********************************************************************************************************* ** 函數名稱: API_CacheDmaMallocAlign ** 功能描述: 開辟一塊非緩沖的內存, 指定內存對齊關系 ** 輸 入 : ** stBytes 長度 ** stAlign 對齊字節數 ** 輸 出 : 開辟的空間首地址 *********************************************************************************************************/ PVOID API_CacheDmaMallocAlign (size_t stBytes, size_t stAlign) {size_t stAlignMax;//判定stAlign是否為2的冪次if (stAlign & (stAlign - 1)) {_ErrorHandle(EINVAL);return (LW_NULL);}stAlignMax = (stAlign > LW_CFG_CPU_ARCH_CACHE_LINE) ? stAlign : LW_CFG_CPU_ARCH_CACHE_LINE;return ((_G_cacheopLib.CACHEOP_pfuncDmaMallocAlign == LW_NULL) ?(__KHEAP_ALLOC_ALIGN(stBytes, stAlignMax)) :(_G_cacheopLib.CACHEOP_pfuncDmaMallocAlign(stBytes, stAlign))); } /********************************************************************************************************* ** 函數名稱: API_CacheDmaFree ** 功能描述: 歸還一塊非緩沖的內存 ** 輸 入 : ** pvBuf 開辟時的首地址 ** 輸 出 : NONE *********************************************************************************************************/ VOID API_CacheDmaFree (PVOID pvBuf) {if (_G_cacheopLib.CACHEOP_pfuncDmaFree) {_G_cacheopLib.CACHEOP_pfuncDmaFree(pvBuf);} else {__KHEAP_FREE(pvBuf);} } /********************************************************************************************************* ** 函數名稱: API_CacheDmaFlush ** 功能描述: DMA 區域 CACHE 將所有或者指定的數據項清空(回寫入內存) ** 輸 入 : pvAdrs 虛擬地址 ** stBytes 長度 ** 輸 出 : ERROR_NONE *********************************************************************************************************/ INT API_CacheDmaFlush (PVOID pvAdrs, size_t stBytes) {return ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(API_CacheFlush(DATA_CACHE, pvAdrs, stBytes)) : (ERROR_NONE)); } /********************************************************************************************************* ** 函數名稱: API_CacheDmaInvalidate ** 功能描述: DMA 區域 CACHE 使部分或全部表項無效(訪問不命中) ** 輸 入 : pvAdrs 虛擬地址 ** stBytes 長度 ** 輸 出 : ERROR_NONE *********************************************************************************************************/ INT API_CacheDmaInvalidate (PVOID pvAdrs, size_t stBytes) {return ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(API_CacheInvalidate(DATA_CACHE, pvAdrs, stBytes)) : (ERROR_NONE)); } /********************************************************************************************************* ** 函數名稱: API_CacheDmaClear ** 功能描述: DMA 區域 CACHE 使部分或全部清空(回寫內存)并無效(訪問不命中) ** 輸 入 : pvAdrs 虛擬地址 ** stBytes 長度 ** 輸 出 : ERROR_NONE *********************************************************************************************************/ INT API_CacheDmaClear (PVOID pvAdrs, size_t stBytes) {return ((_G_cacheopLib.CACHEOP_pfuncDmaMalloc == LW_NULL) ?(API_CacheClear(DATA_CACHE, pvAdrs, stBytes)) : (ERROR_NONE)); }arch層實現源碼
以arm體系結構為例,其他體系結構類似。
#if LW_CFG_VMM_EN > 0pcacheop->CACHEOP_pfuncDmaMalloc = API_VmmDmaAlloc;pcacheop->CACHEOP_pfuncDmaMallocAlign = API_VmmDmaAllocAlign;pcacheop->CACHEOP_pfuncDmaFree = API_VmmDmaFree; #endif /********************************************************************************************************* ** 函數名稱: API_VmmDmaAlloc ** 功能描述: 從物理內存區分配連續的物理分頁, 主要用于 DMA 連續物理內存操作. ** 輸 入 : stSize 需要分配的內存大小 ** 輸 出 : 連續分頁首地址 (物理地址, 此地址對應的物理地址存在于 LW_ZONE_ATTR_DMA 區域內) *********************************************************************************************************/ PVOID API_VmmDmaAlloc (size_t stSize) {ULONG ulFlags;#if LW_CFG_CACHE_EN > 0if (API_CacheGetMode(DATA_CACHE) & CACHE_SNOOP_ENABLE) {ulFlags = LW_VMM_FLAG_RDWR;} else #endif /* LW_CFG_CACHE_EN > 0 */{ulFlags = LW_VMM_FLAG_DMA;}return (API_VmmDmaAllocAlignWithFlags(stSize, LW_CFG_VMM_PAGE_SIZE, ulFlags)); } /********************************************************************************************************* ** 函數名稱: API_VmmDmaAllocAlign ** 功能描述: 從物理內存區分配連續的物理分頁, 主要用于 DMA 連續物理內存操作.(可指定內存關系) ** 輸 入 : stSize 需要分配的內存大小 ** stAlign 對齊關系 ** 輸 出 : 連續分頁首地址 (物理地址, 此地址對應的物理地址存在于 LW_ZONE_ATTR_DMA 區域內) *********************************************************************************************************/ PVOID API_VmmDmaAllocAlign (size_t stSize, size_t stAlign) {ULONG ulFlags;#if LW_CFG_CACHE_EN > 0if (API_CacheGetMode(DATA_CACHE) & CACHE_SNOOP_ENABLE) {ulFlags = LW_VMM_FLAG_RDWR;} else #endif /* LW_CFG_CACHE_EN > 0 */{ulFlags = LW_VMM_FLAG_DMA;}return (API_VmmDmaAllocAlignWithFlags(stSize, stAlign, ulFlags)); } /********************************************************************************************************* ** 函數名稱: API_VmmDmaAllocAlignWithFlags ** 功能描述: 從物理內存區分配連續的物理分頁, 主要用于 DMA 連續物理內存操作.(可指定內存關系) ** 輸 入 : stSize 需要分配的內存大小 ** stAlign 對齊關系 ** ulFlags 映射類型 ** 輸 出 : 連續分頁首地址 (物理地址, 此地址對應的物理地址存在于 LW_ZONE_ATTR_DMA 區域內) *********************************************************************************************************/ PVOID API_VmmDmaAllocAlignWithFlags (size_t stSize, size_t stAlign, ULONG ulFlags) {REGISTER ULONG ulPageNum = (ULONG) (stSize >> LW_CFG_VMM_PAGE_SHIFT);REGISTER size_t stExcess = (size_t)(stSize & ~LW_CFG_VMM_PAGE_MASK);REGISTER PLW_VMM_PAGE pvmpage;ULONG ulZoneIndex;ULONG ulError;if (stAlign & (stAlign - 1)) {return (LW_NULL);}if (stAlign < LW_CFG_VMM_PAGE_SIZE) {stAlign = LW_CFG_VMM_PAGE_SIZE;}if (stExcess) {ulPageNum++;}if (ulPageNum < 1) {_ErrorHandle(EINVAL);return (LW_NULL);}pvmpage = __vmmPhysicalPageAllocAlign(ulPageNum, stAlign, LW_ZONE_ATTR_DMA,&ulZoneIndex); /* 分配連續物理頁面 */ulError = __vmmLibPageMap(pvmpage->PAGE_ulPageAddr, /* 不使用 CACHE */pvmpage->PAGE_ulPageAddr,ulPageNum, ulFlags); /* 映射邏輯物理同一地址 */pvmpage->PAGE_ulMapPageAddr = pvmpage->PAGE_ulPageAddr;pvmpage->PAGE_ulFlags = ulFlags; /* 記錄分頁類型 */__areaPhysicalInsertPage(ulZoneIndex, pvmpage->PAGE_ulPageAddr, pvmpage); /* 插入物理空間反查表 */return ((PVOID)pvmpage->PAGE_ulPageAddr); /* 直接返回物理內存地址 */ }總結
以上是生活随笔為你收集整理的SylixOS中的动态内存分配【14】--- cache API中的非缓存内存分配接口实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【PLC】西门子S7-1200 WINC
- 下一篇: android修改猎豹浏览器,猎豹And