描述了在實(shí)時(shí)嵌入式系統開(kāi)發(fā)中遇到的與CACHE有關(guān)的問(wèn)題。對引起這些問(wèn)題的原因——CACHE和RAM的不一致性進(jìn)行了討論。最后,提出了解決問(wèn)題的方法。 隨著(zhù)社會(huì )的發(fā)展、人們生活水平的提高,人們對嵌入式計算機應用的要求也越來(lái)越高。因此,對嵌入式系統的性能要求也越來(lái)越高。明顯體現在嵌入式系統的CPU速度的不斷提高上。但問(wèn)題也隨之而來(lái),嵌入式CPU的主頻不斷地提高,一方面加強了CPU的處理能力,另一方面,在速度上造成了與慢速的系統存儲器極不相配的情況,從而影響了整個(gè)系統的性能。 為了解決這個(gè)問(wèn)題,引入了CACHE技術(shù)。CACHE是一種高速緩沖存儲器,是為了解決CPU和主存之間速度不匹配而采用的一項重要技術(shù)。通過(guò)在主存和高速CPU之間設置一個(gè)小容量的高速存儲器,在其中存放CPU常用的指令和數據,CPU對存儲器的訪(fǎng)問(wèn)主要體現在對SRAM的存取,CPU可以不必加等待狀態(tài)而保持高速操作。 采用CACHE技術(shù),解決了CPU與主存之間速度不匹配的問(wèn)題;但它又帶來(lái)了一些其它問(wèn)題,如本文將提到的一致性問(wèn)題。 1 問(wèn)題的發(fā)現與原因 在進(jìn)行某嵌入式系統項目的開(kāi)發(fā)過(guò)程中,有一個(gè)環(huán)節需要使用DMA方式進(jìn)行數據傳輸。當程序運行后,發(fā)現傳到目的地的數據塊中經(jīng)常會(huì )有一些錯誤的字節。如:數據本應為00 01 02 03 04 05 06 07 08 09 0A 0B ...(16進(jìn)制),結果卻是00 01 02 03 00 00 00 00 08 09 0A 0B ...。在某些環(huán)節也出現了類(lèi)似的問(wèn)題。例如,通過(guò)HDLC通道向外發(fā)送數據,發(fā)送的總是緩沖區初始化時(shí)的內容,實(shí)際要發(fā)送的數據總是發(fā)不出去,但使用調試工具看內存中的數據,卻是正確的。 經(jīng)過(guò)一段時(shí)間的調試,發(fā)現出現這種現象的環(huán)節都使用了DMA傳輸數據。在通過(guò)HDLC通道發(fā)送數據的例子中,HDLC通道內部也是用DMA方式從內存直接讀數據并向外發(fā)送。經(jīng)過(guò)分析,認為問(wèn)題的原因是出在CACHE上,是由于CACHE數據與內存數據的不一致性造成的。 所謂CACHE數據與內存數據的不一致性,是指:在采用CACHE的系統中,同樣一個(gè)數據可能既存在于CACHE中,也存在于主存中,數據一樣則具有一致性,數據若不一樣就叫做不一致性。具體表現在兩個(gè)方面: (1)更新時(shí)可能CACHE中的數據更新,而主存未更新,則造成數據丟失; (2)在有DMA控制器的系統和多處理器系統中,有多個(gè)部件可以訪(fǎng)問(wèn)主存。這時(shí),可能其中有些部件是直接訪(fǎng)問(wèn)主存,也可能每個(gè)DMA部件和處理器配置一個(gè)CACHE。這樣,主存的一個(gè)區塊可能對應于多個(gè)CACHE中的一個(gè)區塊。于是會(huì )產(chǎn)生主存中的數據被某個(gè)總線(xiàn)部件更新過(guò),而某個(gè)CACHE中的內容未更新,造成數據過(guò)時(shí)。 2 問(wèn)題的分析 要解釋這個(gè)問(wèn)題,首先要了解CACHE的工作模式。CACHE的基本工作模式有兩種:write-through模式和 copyback模式。在write-through模式下,所有的寫(xiě)操作都寫(xiě)入CACHE和RAM,保證了CACHE和RAM的一致。然而,每次對RAM都有寫(xiě)操作會(huì )使處理器的處理能力降低,并且占用總線(xiàn)帶寬。在copyback模式下,寫(xiě)操作只寫(xiě)入CACHE,不寫(xiě)入RAM,從而提高了處理器性能和總線(xiàn)帶寬。copyback模式下,CACHE中的內容只有在需要的時(shí)候才寫(xiě)到RAM中。當CACHE中無(wú)可用空間時(shí),一般使用最近最少使用算法(LRU)來(lái)決定哪一個(gè)CACHE項被替換。copyback模式提供了很高的系統性能,但是需要更多的一致性作保證。為了便于理解,給出一個(gè)使用了CACHE的系統的邏輯框圖,如圖1所示。 該系統中兩個(gè)地方會(huì )發(fā)生CACHE的不一致性: (1)數據CACHE / RAM 數據CACHE與RAM之間的問(wèn)題源于處理器和其他總線(xiàn)控制器對RAM的異步讀寫(xiě)訪(fǎng)問(wèn)。DMA設備和其他總線(xiàn)控制器對RAM的訪(fǎng)問(wèn)是引起CACHE一致性問(wèn)題的主要原因,這個(gè)問(wèn)題可以通過(guò)在程序中加入一些代碼來(lái)解決。 (2)共享CACHE LINE 當一個(gè)CACHE LINE被兩個(gè)以上的線(xiàn)程共享時(shí),也會(huì )產(chǎn)生一致性問(wèn)題。當某個(gè)線(xiàn)程使一個(gè)CACHE LINE無(wú)效時(shí),這個(gè)CACHE LINE中的一些項可能屬于另外一個(gè)線(xiàn)程。這個(gè)問(wèn)題也可以通過(guò)一定的方法來(lái)避免,只要在分配內存時(shí)大小是CACHE LINE大小的整數倍即可。 在哈佛體系結構、copyback模式和無(wú)軟件干預的前提下,最佳的保持一致性的方法就是使用具有總線(xiàn)監聽(tīng)能力的硬件。將CACHE、RAM、DMA設備和其它所有的總線(xiàn)主控設備都連到一個(gè)物理總線(xiàn)上,以使CACHE可以對該總線(xiàn)上的總線(xiàn)交互過(guò)程進(jìn)行監聽(tīng),CACHE將對總線(xiàn)上的地址周期和控制(讀/寫(xiě))比特監聽(tīng),數據周期則被延遲到需要時(shí)才進(jìn)行。當CACHE中的一項被一個(gè)異步操作修改時(shí),該CACHE項就會(huì )被標為無(wú)效。如果處理器對一個(gè)已經(jīng)被標為無(wú)效的CACHE項進(jìn)行訪(fǎng)問(wèn)時(shí),CACHE就會(huì )從RAM中重新載入有效數據。在copyback模式下,處理器對CACHE進(jìn)行寫(xiě)操作時(shí),RAM相應地址中的內容就變成過(guò)時(shí)。如果另外一個(gè)設備想訪(fǎng)問(wèn)RAM中的這部分內容,CACHE就會(huì )搶占該訪(fǎng)問(wèn)周期,將有效的數據寫(xiě)入RAM。然后被搶占的訪(fǎng)問(wèn)周期重新開(kāi)始并將讀到RAM中的有效數據。但是,目前提供監聽(tīng)能力的板子并不多。 3 解決的方法 根據上面的分析和討論,可見(jiàn)問(wèn)題正是由數據CACHE / RAM的不一致性引起的。雖然關(guān)掉CACHE就可以解決一致性的問(wèn)題,并且能夠減小程序開(kāi)發(fā)的復雜度。但是一個(gè)高性能的系統是需要CACHE的,關(guān)掉CACHE會(huì )大大降低系統的性能。因此,本文僅討論在程序中加入代碼來(lái)克服一致性問(wèn)題的方法。 可以采用以下幾種加入代碼的方法來(lái)解決一致性的問(wèn)題?本文使用WIND RIVER公司的嵌入式實(shí)時(shí)多任務(wù)操作系統VxWORKS,下面的函數都是VxWORKS提供的 : (1)對于時(shí)間上不是那么關(guān)鍵的程序段,可以先用下面的代碼維護數據CACHE的一致性。 cacheInvalidate DATA_CACHE address bytes / 輸入緩沖區/ ... cacheFlush DATA_CACHE address bytes /輸出緩沖區/ (2)對于時(shí)間上比較關(guān)鍵的程序段采用如下原則:在每次使用輸出緩沖區前將其更新;在每次使用輸入緩沖區前使其無(wú)效。 將緩沖區標示為“non-cacheable”可以防止一致性問(wèn)題,這需要MMU支持。在分配緩沖區時(shí),將其標示為“non-cacheable”即可。然而,動(dòng)態(tài)緩沖區在釋放時(shí)要標為“cacheable”,否則內存總會(huì )產(chǎn)生大量的緩沖區碎片。 下面給出一個(gè)高性能的驅動(dòng)程序例子,它把更新/無(wú)效的概念進(jìn)行了擴展。不是對整個(gè)CACHE系統,而是對每一個(gè)緩沖區都這樣做。即通過(guò)分配對CACHE安全的緩沖區,在一個(gè)緩沖區的基礎上操作,從而防止了不需要的更新/無(wú)效操作。在這個(gè)例子中使用了CACHE庫中的函數cacheDMAMalloc? ,宏CACHE_DMA_INVALIDATE和CACHE_DMA_FLUSH實(shí)現一致性。在第4行調用函數cacheDMAMalloc 后,如果指針?lè )祷貫榉强?則說(shuō)明分配到了一塊對于一致性問(wèn)題來(lái)說(shuō)是安全的緩沖區。 第7行驅動(dòng)程序在緩沖區中寫(xiě)入要傳給外部設備的數據,在第9行準備傳給外設之前,驅動(dòng)程序必須更新數據CACHE以保證要傳的數據是在內存中,而不是在CACHE中。 當驅動(dòng)程序準備讀外設傳給內存的數據,在第13行驅動(dòng)程序處理這些數據之前,必須使數據CACHE中對應于輸入緩沖區的那部分無(wú)效以消除這些包含過(guò)時(shí)內容的條目。之后,驅動(dòng)程序才能安全地處理從內存中取來(lái)的輸入數據。 1: STATUS drvExample pBuf 2: void pBuf / 緩沖區指針 / 3: { /* 4: pBuf = cacheDMAMalloc BUF_SIZE 5: if pBuf == NULL 6: return ERROR /內存分配失敗/ 7: /其它初始化代碼和向發(fā)送緩沖區填數據/ 8: CACHE_DMA_FLUSH pBuf BUF_SIZE 9: drvWrite pBuf /向外設發(fā)送數據/ 10: …… / 其它代碼 / 11: drvWait /等待外設來(lái)的數據/ 12: CACHE_DMA_INVALIDATE pBuf BUF_SIZE 13: / 處理外設來(lái)的數據 / 14: cacheDMAFree pBuf /釋放內存 / 15: return OK 16:} |