Cache—高速緩存存儲器
高速緩衝存儲器(Cache)其原始意義是指存取速度比一般隨機存取記憶體(RAM)來得快的一種RAM,一般而言它不像系統主記憶體那樣使用DRAM技術,而使用昂貴但較快速的SRAM技術,也有快取記憶體的名稱。
高速緩衝存儲器是存在於主存與CPU之間的一級存儲器, 由靜態存儲芯片(SRAM)組成,容量比較小但速度比主存高得多, 接近於CPU的速度。在計算機存儲系統的層次結構中,是介於中央處理器和主存儲器之間的高速小容量存儲器。它和主存儲器一起構成一級的存儲器。高速緩衝存儲器和主存儲器之間信息的調度和傳送是由硬件自動進行的。
高速緩衝存儲器最重要的技術指標是它的命中率。
爲什麼需要引入cache
需要了解第一點,CPU與sdram相應時間並非一致,在訪問sdram時,需要等待幾個機械週期,這個幾可能上千個機械週期,對於不斷訪問同一塊的地址,這就需要浪費一定的時間。
引入cache的原因就在於我能夠將重複使用的數據以及指令,放入cache,然後之後取數據和指令就能直接在cache裏面取。
cache運行過程
cache miss:緩衝器中沒有這個數據
cache fill:向cache填入該數據以及之後一個line的數據,這裏需要注意一個line是8個字,這裏的字不一定是兩個字節,對於32位的sdram,一個字是4個字節,8個字就是32字節。
注意:這裏fill第一次數據會返回給CPU,也就是這裏會操作兩步,一步是cache fill 一步是返回數據。
cache hit:CPU在cache中找到這個數據或指令。
協處理器
cp15就是s3c2440裏面的協處理器,一共有16個。具體意思不用詳細學習。
instruction cache :ICache指令緩衝
data cache :DCache指令緩衝
這裏補充一個概念,還有write buffer,對於寫操作,並不是直接寫入sdram中,首先我們寫到cahce裏面,然後機器把數據刷到write buffer裏面,write buffer在寫進sdram裏面去。所以對於一些我們需要即時操作的硬件,我們不能開通write buffer,cache兩個功能,例如IO口的操作,需要馬上傳出或者馬上傳入;顯存需要電子槍馬上打上屏幕;sdram可以開通。
協處理器指令
r:register
c:co-process
使能cpu中的icache
enable_icache:
/*設置協處理器使能icache*/
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #(1<<12) /*r0 = r0 or (1<<12)*/
mcr p15, 0, r0, c1, c0, 0
mov pc,lr```
MMU–地址映射控制器
首先介紹一個概念,地址映射是什麼?我們用一個虛擬地址表示一個真實地址就是地址映射。
再者明確一個概念,多個app同時運行時我們不可能手動去分配所有app的鏈接地址,所以需要我們映射出app的真實地址,在程序運行時自動去找到相應的地址,執行。
引入虛擬地址的原因
利用同一個地址如何得到不同app的真實地址
根據不同進程的pid號得到不同的映射地址
在程序中我們不區分MVA和VA,一般指的是MVA。
如何使用MMU
首先需要創建一個頁表,頁表在sdram中一段沒有使用的地址,需要告訴MMU這個頁表的首地址。最簡單就是一個表格,一一對應,裏面存放虛擬地址VA和物理地址PA。但是這樣就浪費空間,多了一個VA地址。
section base addre是用PA取高20位得到的。
這是1級頁表的描述格式,也就說這是實際在頁表中存在的東西,物理地址只是一部分。
權限管理
一共16個域,domain佔4位0-15,就是16個域,0對應c3裏面的第一個0域。15對應c3裏面的最後一個15域。
創建頁表
#define MMU_SECDESC_AP (3<<10)
#define MMU_SECDESC_DOMAIN (0<<5)
#define MMU_SECDESC_NCNB (0<<2)
#define MMU_SECDESC_WB (3<<2)
#define MMU_SECDESC_TYPE ((1<<4) | (1<<1))
#define MMU_SECDESC_FOR_IO (MMU_SECDESC_AP | MMU_SECDESC_DOMAIN | MMU_SECDESC_NCNB | MMU_SECDESC_TYPE)
#define MMU_SECDESC_FOR_MEM (MMU_SECDESC_AP | MMU_SECDESC_DOMAIN | MMU_SECDESC_WB | MMU_SECDESC_TYPE)
#define IO 1
#define MEM 0
void create_secdesc(unsigned int *ttb, unsigned int va, unsigned int pa, int io)
{
int index;
index = va / 0x100000;
if (io)
ttb[index] = (pa & 0xfff00000) | MMU_SECDESC_FOR_IO;
else
ttb[index] = (pa & 0xfff00000) | MMU_SECDESC_FOR_MEM;
}
/*
* VA PA CB
* 0 0 00
* 0x40000000 0x40000000 11
*
* 64M sdram:
* 0x30000000 0x30000000 11
* ......
* 0x33f00000 0x33f00000 11
*
* register: 0x48000000~0x5B00001C
* 0x48000000 0x48000000 00
* .......
* 0x5B000000 0x5B000000 00
*
* Framebuffer : 0x33c00000
* 0x33c00000 0x33c00000 00
*
* link address:
* 0xB0000000 0x30000000 11
* */
void create_page_table(void)
{
/*1.頁表在哪裏?0x3200 0000(16KB)只需要指向一塊沒有用到的地址就可以*/
/*ttb:translation table base*/
unsigned int *ttb = (unsigned int *)0x32000000;
unsigned int va, pa;
int index;
/*2.根據va,pa設置頁表條目*/
/*2.1 for sram/nor flash*/
/*nand啓動0地址是sram的0地址,nor啓動0地址是nor flash的0地址*/
create_secdesc(ttb, 0, 0, IO); /*這裏用NCNB模式的原因是之後會通過寫數據至0地址然後讀出來,從而判定是nor還是nand啓動*/
/*如果使用cache和buffer,寫數據以及讀數據都會寫/讀到cache,這樣就會導致讀出的內容就是寫進去的內容*/
/*然後cpu就一直認爲是nand啓動,從而出錯*/
/* 2.2 for sram when nor boot */
create_secdesc(ttb, 0x40000000, 0x40000000, MEM);
/* 2.3 for 64M sdram */
va = 0x30000000;
pa = 0x30000000;
for (; va < 0x34000000;)
{
create_secdesc(ttb, va, pa, MEM);
va += 0x100000;
pa += 0x100000;
}
/* 2.4 for register: 0x48000000~0x5B00001C */
va = 0x48000000;
pa = 0x48000000;
for (; va <= 0x5B000000;)
{
create_secdesc(ttb, va, pa, IO);
va += 0x100000;
pa += 0x100000;
}
/* 2.5 for Framebuffer : 0x33c00000 */
create_secdesc(ttb, 0x33c00000, 0x33c00000, IO);
/* 2.6 for link address */
create_secdesc(ttb, 0xB0000000, 0x30000000, MEM);
}
由於頁表是以1M對齊,所以register 地址需要寫成0x5B000000,
使能icache,dcache,mmu。
CP15中c2管理一級頁表基址,以16KB對齊。
我們需要些這個協處理器,所以0–13位需要寫爲0,相當於是16KB對齊。
mmu_enable:
/*把頁表基地址告訴cp15*/
ldr r0, =0x32000000
mcr p15, 0, r0, c2, c0, 0 /*將r0的值寫進協處理器cp15中的c2(c0和後面的0用區分是哪一個c2,可能有多個c2)*/
/*設置域爲0xffffffff,不進行權限檢查*/
ldr r0, =0xffffffff
mcr p15, 0, r0, c3, c0, 0
/*使能icache,dcache,mmu*/
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #(1<<12) /* enable icache */
orr r0, r0, #(1<<2) /* enable dcache */
orr r0, r0, #(1<<0) /* enable mmu */
mcr p15, 0, r0, c1, c0, 0
mov pc, lr
設置域的處理的方式,在頁表中已經選擇過0域。
本來應該只設置BIT[0,1]兩個位置,這樣寫就是每個域都是這個權限。