1. Vxworks下的高速緩沖存儲器一致性問(wèn)題 美國風(fēng)河(Wind River)公司的VxWorks是目前最先進(jìn)的實(shí)時(shí)嵌入式操作系統。Tornade是它的集成一體開(kāi)發(fā)環(huán)境。然而,VxWorks下編程硬件驅動(dòng)程序時(shí)卻存在著(zhù)高速緩沖存儲器一致性(Cache Coherence)的問(wèn)題。該系統下有兩個(gè)cache區:數據高速緩沖存儲器和指令高速緩沖存儲器。本文討論的高速緩沖存儲器問(wèn)題均指數據高速緩沖存儲器。 高速緩沖存儲器一致性問(wèn)題是指高速緩沖存儲器中的數據必須與內存中的數據保持同步(一致)。這個(gè)問(wèn)題常發(fā)生在CPU內核與另一個(gè)設備異步訪(fǎng)問(wèn)內存時(shí)。 高速緩沖存儲器可以工作在Write-through或copyback模式。在Write-through模式下,數據輸出時(shí),系統會(huì )把數據同時(shí)寫(xiě)入高速緩沖存儲器和內存中。這樣就保證了輸出時(shí)的高速緩沖存儲器一致性。但該模式卻無(wú)法解決輸入時(shí)的高速緩沖存儲器一致性問(wèn)題.在Copyback模式下。系統只寫(xiě)數據到高速緩沖存儲器中,因此對于數據輸入和輸出都存在高速緩沖存儲器一致性問(wèn)題。 VxWorks下通常有兩種方法解決高速緩沖存儲器一致性問(wèn)題。 (1)Cache-safe buffer(即non-cacheable 的buffer)。這種情況下,CPU讀數據時(shí)會(huì )從內存中讀取.而不是從高速緩沖存儲器中讀。憾鳦PU寫(xiě)數據時(shí)則同時(shí)寫(xiě)入高速緩沖存儲器和內存. 該方案可通過(guò)以下兩種方法實(shí)現. * 在內存段屬性中定義此段buffer,空間屬性為non-cacheable; * 在內存管理單元MMU支持下,用cacheDmaMalloc()/cacheDmaFree()獲得此段buffer。則此段buffer是non-cacheable的(注意無(wú)MMU時(shí)。分配的buffer是cacheable。此法不支持這種情況)。 (2)對于cacheable的buffer空間,采用flush()/invalidate()函數或宏來(lái)配合讀/寫(xiě)使用此段buffer空間。flush()將高速緩沖存儲器中的數據寫(xiě)入內存。invalidate()則將內存中數據寫(xiě)入高速緩沖存儲器。這兩個(gè)函數都保證了高速緩沖存儲器與內存同步。 實(shí)際flush()/invalidate()函數有如下兩組,功能相同稍有區別: 組1:CACHE_DMA_FLUSH()函數和CACHE_DMA_INVALIDATE()函數 組2:cacheFlush()函數和cacheInvalidate()函數 第一組實(shí)際是2個(gè)宏,與cacheDmaMalloc()函數配合使用。 2. MPC860上高速緩沖存儲器一致性的軟件設計方法 MPC860是摩托羅拉公司的32位多用途集成通信控制器。主要包括一個(gè)32位的嵌入式PowerPC core。一個(gè)通信處理模塊CPM,一個(gè)系統集成模塊SIM60及一個(gè)獨立的快速以太網(wǎng)FEC模塊。在VxWorks下編寫(xiě)MPC860的驅動(dòng)程序。要保護的是CPM、FEC模塊的發(fā)送/接收緩沖區描述符TXBD/RXBD及其對應的緩沖區對于MPC860開(kāi)發(fā)中象BD(Buffer DescriptiOn)這樣的靜態(tài)空間適合采用cache-safe boffer方法。即采用第1種方法: 而對BD域中對應的緩沖區,由于該緩沖區多是動(dòng)態(tài)分配和釋放,更適合采用第2種方法,即采用flush()/invalidate()函數或宏來(lái)配合讀/寫(xiě)使用此段緩沖區空間。這樣可以避免將整個(gè)的包括還未分配的空間都預先標記為non-cacheable而造成效率低下。具體可以采用下面的方法: (1)TXBD/RXBD放在MPC860雙口RAM中。并在板級支持包BSP文件Syslib.c中的頁(yè)描述符數據結構 svsPhysMemDesc[]中定義860上所有64K內存空間為non-cachable的緩沖區。從而不必做cache coherence的保護了。 (2)對應TXBD/RXBD中數據指針域的發(fā)/收緩沖區均用cache DmaMalloc()獲得(具體是指初始化時(shí)給所有接收RXBD掛接的初始緩沖區和接收幀函數中給RXBD掛接的新緩沖區.以及在應用層中使用的發(fā)送TXBD對應的緩沖區)。而用cacheDmaFree()釋放。同時(shí)發(fā)送幀函數中用cacheFlush()函數保護待發(fā)送TXBD對應的緩沖區:接收幀函數中用cache Invalidate()函數保護已經(jīng)裝載了接收數據的接收緩沖區。以快速以太網(wǎng)FEC的驅動(dòng)程序為例,保護具體實(shí)現如下: /* FEC發(fā)送幀函數 */ FEC_SEND_FRAME() { /* 填寫(xiě)發(fā)送buffer內容,實(shí)際填寫(xiě)在data cache中 */ sptr_tx_buffer[i]=data; fec.txBd.dataPointer=(char*)sptr_tx_buffer; /*將填寫(xiě)在data cache中的內容寫(xiě)回內存中的實(shí)際發(fā)送buffer(即以sptr_tx_buffer為地址的內存)中*/ cacheFlush(DATA_CACHE,sptr_tx_buffer,1518); /*啟動(dòng)發(fā)送命令,FEC控制器發(fā)送內存中buffer內容而非data cache中內容*/ *(UINT32*)VXImmrGet()+MOT_FEC_TX_ACT_OFF))=MOT_FEC_TX_ACT; } /*FEC接收幀函數*/ FEC_RECEIVE_FRAME() { /*取得實(shí)際接收buffer的地址*/ pBuffer=(void*)fec.rxBd.dataPointer; /*將RXBD對應的內存中接收buffer中內容寫(xiě)回data cache中*/ cacheInvalidate(DATA_CACHE,pBuffer,1520); *vptr_buffer=pBuffer; /*以后CPU可以安全使用接收buffer中的內容**vptr_buffer了*/ } if ((pBuffer = (void *)malloc (allocBytes)) == NULL) return (NULL); /* Flush any data that may be still sitting in the cache */ cacheClear (DATA_CACHE, pBuffer, allocBytes); cacheInvalidate (INSTRUCTION_CACHE, pBuffer, allocBytes); |