關於DMA,TCM(ITCM和DTCM)和Cache的理解

         <!--一個博主專欄付費入口結束-->
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
                                    <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-d284373521.css">
            <div class="htmledit_views" id="content_views">
                                        <h1><a name="t0"></a>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;關於DMA,TCM(ITCM和DTCM)和Cache</h1>

DMA


DMA=Direct Memory Access。這是一種通過硬件實現的數據傳輸機制。簡單的說,就是不在CPU的參與下完成數據的傳輸。
DMA是一種硬件設備。這種設備的工作原理是這樣的:
——首先CPU告訴DMA設備,要有一堆數據需要傳輸,爲了效率而請它出馬。(DMA請求)
——DMA收到CPU的消息,開始準備。此時CPU把數據源地址、數據目標地址、傳輸數據量、傳輸模式等等參數告訴它。(DMA初始化)
——DMA初始化完,向CPU發送消息“借你的總線用一用,我要開始傳輸數據了!”(總線出借,DMA啓動)
——CPU收到消息後,暫時切斷自己與總線的聯繫。DMA開始傳輸數據。(DMA數據)
——DMA傳輸完數據之後,向CPU發送消息“搞定了!總線還給你。”(總線歸還)
——CPU說:“幹得好!老將出馬一個頂倆!辛苦了,你先歇着吧。”DMA設備停止。CPU該幹啥幹啥。
由於是硬件實現的,所以DMA的速度非常快。快到什麼程度呢?在DS上,尤其是數據量非常大的時候,相比於CPU當中介,效率能夠提高一百萬倍以上。
由於DMA的速度是如此之快,所以大量的數據傳輸,一般都要求使用DMA。

 

TCM


TCM=Tightly Coupled Memory,是一種高速緩存,據說是被直接集成在CPU芯片中。DS有兩種TCM,分別是ITCM(Instruction TCM)和DTCM(Data TCM)。

注意:

1.內存支持列表中,內存詳細參數裏,SS指的是單面內存,DS指的是雙面內存。內存一共有兩面,根據內存總容量和內存芯片的存儲容量,內存廠家會生產雙面內存和單面內存,也就是內存的兩面都有存儲芯片,或者只有一面有存儲芯片。單雙面內存在兼容性上有一定區別,所以會單獨列出來。

2。ITCM是cortex內核中指令傳輸總線,DTCM是cortex內核中數據傳輸總線
是cpu內核同flash及sram之間傳輸指令和數據的通道,指令的取指和執行及數據的讀寫在性能及管理上存在差異性,因而需要予以區分。

由於是高速緩存,所以這兩塊內存區域被當做特殊的用途。比如某些對時間要求非常嚴格的代碼,就可以被放到ITCM中執行。這可以有效地提高運行速度。某些需要頻繁存取的數據,也可以放到DTCM中以節省存取時間。
怎麼樣把代碼放到ITCM中?有兩種方法。一種是使用gcc特有的“屬性標籤”,將指定代碼賦予“ITCM”屬性,此時該代碼會被載入ITCM中執行。還有一種方法是直接將.c源文件改成.itcm.c,此時源文件會被直接編譯成在ITCM中運行的目標文件。
而DTCM就方便得多了。雖然兩個TCM都是可映射的,也就是說,它們的地址並非固定,但是一般會將其分別映射到固定地址。既然已經有了固定地址,那麼就可以很輕鬆地訪問了。不過,正如剛纔所說的,這兩塊內存空間都是有特殊用途的,所以不建議直接訪問。相比於ITCM來說,DTCM更加重要。因爲在這塊內存中,存在着一個非常重要的對象——棧。局部變量和函數調用的參數,就是靠棧進行傳遞的。由於DMA無法訪問TCM,所以也就無法訪問棧。又由於局部變量是被開闢到棧中,所以DMA也無法對局部變量進行傳遞。


Cache

衆所周知CPU的速度非常快。當CPU訪問外設的時候,有些外設速度比較慢,響應CPU比較遲鈍。此時CPU要麼等外設響應,要麼繼續幹它的活等外設的中斷信號。但是有些外設是沒有中斷的。此時CPU就必須等了。最典型的例子就是內存。當CPU訪問內存的時候,並非像你想象的那樣,CPU立刻就能訪問到它想訪問的內存空間,而是有一個“WaitState”的過程。想想看吧,每訪問一次內存都要等上幾個機器週期,這可不是個好事~~~尤其是,這個“幾”可不是簡單的一位數,有些時候甚至能達到3位數。
那麼這個問題又該怎麼解決呢?那就是Cache了。
Cache是集成在CPU內部的極高速的緩存。注意關鍵詞“極高速”。一般來說,它的訪問速度幾乎可以媲美CPU。這就意味着,CPU在訪問Cache的時候幾乎不會浪費多少時間。不過,速度的提升是用容量作爲代價的。Cache的容量很小。

那麼,我們把常用的數據放到Cache中,CPU在訪問的時候直接訪問Cache就行了,不用耗費時間去訪問內存了。
事實上CPU就是這麼做的。在讀內存的時候,CPU首先讀Cache,看看有沒有它想要的數據的“副本”,有的話那就太好了,直接拿過去用。沒有的話就只好費點功夫去讀內存了。而在寫內存的時候,CPU直接寫到Cache中,而非直接寫到內存中。Cache寫滿了之後,此時纔將Cache中的數據更新到內存,同時清空Cache。就像寄信一樣,所有的信件會首先攢到郵局,到達一定數量之後纔會送出去。
不過這又出現一個問題:假如Cache中有某個內存數據的“副本”,那麼CPU在讀該內存的時候就會直接使用該副本而不用去讀內存。那萬一內存中的數據被改寫,此時CPU再讀該內存,讀出來的豈不是那個舊的副本而不是最新的內存數據?同樣,假如我想DMA一些數據,誰能保證此時內存中的數據就是最新的數據?很可惜,Cache是完全的黑箱。你不知道它的地址。你也無法直接訪問它,但一般系統會提供函數進行cache回寫和clear操作,比如

//將整個Data Cache更新到內存

void DC_FlushAll()

// 清空整個Data Cache
void DC_InvalidateAll()
那麼,什麼時候使用這些函數呢?
在DMA之前,我需要保證數據源內存中的數據是最新的。所以此時需要Flush,從而使DC中的副本能夠更新到內存中。
在DMA之後,我需要保證DC中的副本和內存中的數據是相同的。但是NDSLIB沒有更新DC的函數,所以沒辦法,我們只能把DC中的副本殺掉。此時如果CPU訪問內存,由於DC中沒有副本,所以就只能直接從內存訪問並將訪問到的值作爲DC中副本了。所以此時需要Invalidate
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章