日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

S3C2410 bootloader ----VIVI阅读笔记 (转)下

發布時間:2023/12/2 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 S3C2410 bootloader ----VIVI阅读笔记 (转)下 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 static inline void mem_mapping_linear(void)
2 {
3????? unsigned long pageoffset, sectionNumber;
4??????????? putstr_hex("MMU table base address = 0x", (unsigned long)
mmu_tlb_base);
5?????? /* 4G 虛擬地址映射到相同的物理地址. not cacacheable, not bufferable */
6?????? /* mmu_tlb_base = 0x33dfc000*/
7?????? for (sectionNumber = 0; sectionNumber < 4096; sectionNumber++) {
8?????????????? pageoffset = (sectionNumber << 20);
9???????????????? *(mmu_tlb_base + (pageoffset >> 20)) = pageoffset |
??????????? MMU_SECDESC;
10????? }
11????? /* make dram cacheable */
12????? /* SDRAM物理地址0x3000000-0x33ffffff,
13????????? DRAM_BASE=0x30000000,DRAM_SIZE=64M
14????? */
15????? for (pageoffset = DRAM_BASE; pageoffset < (DRAM_BASE+DRAM_SIZE); \
16????????? pageoffset += SZ_1M) {
17????????? //DPRINTK(3, "Make DRAM section cacheable: 0x%08lx\n",???????????? pageoffset);
18????????? *(mmu_tlb_base + (pageoffset >> 20)) = \
pageoffset | MMU_SECDESC | MMU_CACHEABLE;
19????? }
20 }
mmu_init()函數用于啟動MMU,它直接調用arm920_setup()函數。arm920_setup()的代碼在arch/s3c2410/mmu.c中:
[main(int argc, char *argv[]) > mmu_init( ) > arm920_setup( )]
1 static inline void arm920_setup(void)
2 {
3????????????????? unsigned long ttb = MMU_TABLE_BASE;
/* MMU_TABLE_BASE = 0x33dfc000 */
4 __asm__(
5?????? /* Invalidate caches */
6?????? "mov??? r0, #0\n"
7?????? "mcr??? p15, 0, r0, c7, c7, 0\n"??? /* invalidate I,D caches on v4 */
8?????? "mcr??? p15, 0, r0, c7, c10, 4\n"?? /* drain write buffer on v4 */
9?????? "mcr??? p15, 0, r0, c8, c7, 0\n"??? /* invalidate I,D TLBs on v4 */
?????????? 10????? /* Load page table pointer */
11????? "mov??? r4, %0\n"
12????? "mcr??? p15, 0, r4, c2, c0, 0\n"??? /* load page table pointer */
13????? /* Write domain id (cp15_r3) */
????????? 14????? "mvn??? r0, #0\n"??? /* Domains 0b01 = client, 0b11=Manager*/
????????? 15????? "mcr??? p15, 0, r0, c3, c0, 0\n"
/* load domain access register,write domain 15:0, 用戶手冊P548(access permissions)*/
16????? /* Set control register v4 */
17????? "mrc??? p15, 0, r0, c1, c0, 0\n"??? /* get control register v4 */
??????????? /*數據手冊P545:read control register */
18????? /* Clear out 'unwanted' bits (then put them in if we need them) */
19????? /* ..VI ..RS B... .CAM */?? /*這些位的含義在數據手冊P546*/
20????? "bic r0, r0, #0x3000\n" /* ..11 .... .... .... */
??????????? /*I(bit[12])=0 = Instruction cache disabled*/
21????? /*V[bit[13]](Base location of exception registers)=0 = Low addresses = 0x0000 0000*/
22????? "bic r0, r0, #0x0300\n"????? /* .... ..11 .... .... */
23????? /*R(ROM protection bit[9])=0*/
?????????????????? /*S(System protection bit[8])=0*/
?????????????????? /*由于TTB中AP=0b11(line141),所以RS位不使用(P579)*/
24????? "bic r0, r0, #0x0087\n"????? /* 0x0000000010000111 */
??????????????? /*M(bit[0])=0 = MMU disabled*/
??????????????? /*A(bit[1])=0 =Data address alignment fault checking disable*/
??????????????? /*C(bit[2])=0 = Data cache disabled*/
??????????????? /*B(bit[7])=0= Little-endian operation*/
25????? /* Turn on what we want */
26????? /* Fault checking enabled */
27????? "orr r0, r0, #0x0002\n"????? /* .... .... .... ..10 */
??????????? /*A(bit[1])=1 = Data address alignment fault checking enable*/
28????????????????? #ifdef CONFIG_CPU_D_CACHE_ON???? /*is not set*/
29????? "orr??? r0, r0, #0x0004\n"????? /* .... .... .... .100 */
??????????? /*C(bit[2])=1 = Data cache enabled*/
30 #endif
31 #ifdef CONFIG_CPU_I_CACHE_ON???? /*is not set*/
32????? "orr??? r0, r0, #0x1000\n" /* ...1 .... .... .... */
??????????? /*I(bit[12])=1 = Instruction cache enabled*/
33 #endif
34????????? /* MMU enabled */
35??????????????? "orr??? r0, r0, #0x0001\n"????? /* .... .... .... ...1 */
??????????? /*M(bit[0])=1 = MMU enabled*/
36??????????????? "mcr??? p15, 0, r0, c1, c0, 0\n"??? /* write control register */
??????????? /*數據手冊P545*/
37??????????????? : /* no outputs */
38??????????????? : "r" (ttb) );
39 }
[未完]
S3C2410 bootloader ----VIVI閱讀筆記3
4、Step 4:heap_init()?????
第4步調用了heap_init(void)函數,并返回值。該值是函數heap_init()調用的mmalloc_init()函數的返回值。其實,這步就是申請一塊內存區域。
[lib/heap.c->heap_init(void)]
1??????? int heap_init(void)
2??????? {
3??????????????? return mmalloc_init((unsigned char *)(HEAP_BASE), HEAP_SIZE);??????
4??????? }
內存動態分配函數mmalloc就是從heap(堆)中劃出一塊空閑內存。相應的mfree函數則將動態分配的某塊內存釋放回heap中。
heap_init 函數在SDRAM中指定了一塊1M大小的內存作為heap(起始地址HEAP_BASE = 0x33e00000),并在heap的開頭定義了一個數據結構blockhead。事實上,heap就是使用一系列的blockhead數據結構來描述 和操作的。每個blockhead數據結構對應著一塊heap內存,假設一個blockhead數據結構的存放位置為A,則它對應的可分配內存地址為“A + sizeof(blockhead)”到“A + sizeof(blockhead) + size - 1”。blockhead數據結構在lib/heap.c中定義:
1 typedef struct blockhead_t {
2?????? int32 signature;???? //固定為BLOCKHEAD_SIGNATURE
3?????? bool allocated;????? //此區域是否已經分配出去:0-N,1-Y
4?????? unsigned long size; //此區域大小
5?????? struct blockhead_t *next;?? //鏈表指針
6?????? struct blockhead_t *prev;?? //鏈表指針
7 } blockhead;
現 在來看看heap是如何運作的(如果您不關心heap實現的細節,這段可以跳過)。vivi對heap的操作比較簡單,vivi中有一個全局變量 static blockhead *gHeapBase,它是heap的鏈表頭指針,通過它可以遍歷所有blockhead數據結構。假設需要動態申請一塊sizeA大小的內存,則 mmalloc函數從gHeapBase開始搜索blockhead數據結構,如果發現某個blockhead滿足:
(1) allocated = 0 //表示未分配
(2) size > sizeA,則找到了合適的blockhead,
滿足上述條件后,進行如下操作:
a.allocated設為1
b.如果size – sizeA > sizeof(blockhead),則將剩下的內存組織成一個新的blockhead,放入鏈表中
c.返回分配的內存的首地址釋放內存的操作更簡單,直接將要釋放的內存對應的blockhead數據結構的allocated設為0即可。
heap_init函數直接調用mmalloc_init函數進行初始化,此函數代碼在lib/heap.c中,比較簡單,初始化gHeapBase即可:
[main(int argc, char *argv[]) > heap_init(void) > mmalloc_init(unsigned char *heap, unsigned long size)]
1???????? static inline int mmalloc_init(unsigned char *heap, unsigned long size)
2???????? {
3????? if (gHeapBase != NULL) return -1;
??? 4??? DPRINTK("malloc_init(): initialize heap area at 0x%08lx, size = 0x%08lx\n", heap, size);
5?????? gHeapBase = (blockhead *)(heap);
6?????? gHeapBase->allocated=FALSE;
7?????? gHeapBase->signature=BLOCKHEAD_SIGNATURE;
8?????? gHeapBase->next=NULL;
9?????? gHeapBase->prev=NULL;
10????? gHeapBase->size = size - sizeof(blockhead);
11????? return 0;
12???????? }
static blockhead *gHeapBase = NULL; 這個就是上面稱贊的全局變量了,定義在lib/heap.c中。上面就是個鏈表操作,數據結構,看來搞這個也得好好學數據結構啊,不然內存搞的溢出、浪費可就哭都來不及了。
5、Step 5:mtd_dev_init()???
所 謂MTD(Memory Technology Device)相關的技術。在linux系統中,我們通常會用到不同的存儲設備,特別是FLASH設備。為了在使用新的存儲設備時,我們能更簡便地提供它 的驅動程序,在上層應用和硬件驅動的中間,抽象出MTD設備層。驅動層不必關心存儲的數據格式如何,比如是FAT32、ETX2還是FFS2或其它。它僅 僅提供一些簡單的接口,比如讀寫、擦除及查詢。如何組織數據,則是上層應用的事情。MTD層將驅動層提供的函數封裝起來,向上層提供統一的接口。這樣,上 層即可專注于文件系統的實現,而不必關心存儲設備的具體操作。這段亂七八糟的話也許比較讓人暈,也可以這樣理解在設備驅動(此處指存儲設備)和上層應用之 間還存在著一層,共三層,這個中間層就是MTD技術的產物。通常可以將它視為驅動的一部分,叫做上層驅動,而那些實現設備的讀、寫操作的驅動稱為下層驅 動,上層驅動將下層驅動封裝,并且留給其上層應用一些更加容易簡單的接口。
在我們即將看到的代碼中,使用mtd_info數據結構表示一個MTD 設備,使用nand_chip數據結構表示一個nand flash芯片。在mtd_info結構中,對nand_flash結構作了封裝,向上層提供統一的接口。比如,它根據nand_flash提供的 read_data(讀一個字節)、read_addr(發送要讀的扇區的地址)等函數,構造了一個通用的讀函數read,將此函數的指針作為自己的一個 成員。而上層要讀寫flash時,執行mtd_info中的read、write函數即可。
mtd_dev_init()用來掃描所使用的 NAND Flash的型號,構造MTD設備,即構造一個mtd_info的數據結構。對于S3C2410來說,它直接調用mtd_init(),mtd_init 又調用smc_init(),此函數在drivers/mtd/maps/s3c2410_flash.c中:
[main(int argc,char *argv[])>mtd_dev_init()>mtd_init()]
1??????? int mtd_init(void)
2 {
3 int ret;
4 #ifdef CONFIG_MTD_CFI??????????????? /*is not set*/
5 ret = cfi_init();
6??????? #endif
7??????? #ifdef CONFIG_MTD_SMC9??????????????? /* =y */
8??????????????? ret = smc_init();
9??????? #endif
10??????? #ifdef CONFIG_S3C2410_AMD_BOOT??????? /*is not set*/
11??????????????? ret = amd_init();
12??????? #endif
13??????? if (ret) {
14??????????????? mymtd = NULL;
15??????????????? return ret;
16???????????????? }
17??????? return 0;
18??????? }
顯而易見,該函數應取第二項,這項在autoconf.h中定義了。
[main(int argc, char *argv[]) > mtd_dev_init() > mtd_init() > smc_init()]
1 static int
2 smc_init(void)
3 {
/*struct mtd_info *mymtd,數據類型在include/mtd/mtd.h*/
??????????? /*strcut nand_chip在include/mtd/nand.h中定義*/
4?????? struct nand_chip *this;
5?????? u_int16_t nfconf;
??????????? /* Allocate memory for MTD device structure and private data */
6?????? mymtd = mmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip));
7?????? if (!mymtd) {
8????????? printk("Unable to allocate S3C2410 NAND MTD device structure.\n");
9????????? return -ENOMEM;
10????? }
??????????? /* Get pointer to private data */
11????? this = (struct nand_chip *)(&mymtd[1]);
??????????? /* Initialize structures */
12????? memset((char *)mymtd, 0, sizeof(struct mtd_info));
13????? memset((char *)this, 0, sizeof(struct nand_chip));
/* Link the private data with the MTD structure */
14????? mymtd->priv = this;
/* set NAND Flash controller */
15????? nfconf = NFCONF;
/* NAND Flash controller enable */
16????? nfconf |= NFCONF_FCTRL_EN;
/* Set flash memory timing */
17????? nfconf &= ~NFCONF_TWRPH1;?? /* 0x0 */
??? 18????? nfconf |= NFCONF_TWRPH0_3; /* 0x3 */
??? 19????? nfconf &= ~NFCONF_TACLS; /* 0x0 */
??? 20????? NFCONF = nfconf;
??????????? /* Set address of NAND IO lines */
??? 21????? this->hwcontrol = smc_hwcontrol;
??? 22????? this->write_cmd = write_cmd;
23????? this->write_addr = write_addr;
24????? this->read_data = read_data;
25????? this->write_data = write_data;
26????? this->wait_for_ready = wait_for_ready;
/* Chip Enable -> RESET -> Wait for Ready -> Chip Disable */
27????? this->hwcontrol(NAND_CTL_SETNCE);
28????? this->write_cmd(NAND_CMD_RESET);
29????? this->wait_for_ready();
30????? this->hwcontrol(NAND_CTL_CLRNCE);
31????? smc_insert(this);
32????? return 0;
33 }
6 -14行構造了一個mtd_info結構和nand_flash結構,前者對應MTD設備,后者對應nand flash芯片(如果您用的是其他類型的存儲器件,比如nor flash,這里的nand_flash結構應該換為其他類型的數據結構)。MTD設備是具體存儲器件的抽象,那么在這些代碼中這種關系如何體現呢——第 14行的代碼把兩者連結在一起了。事實上,mtd_info結構中各成員的實現(比如read、write函數),正是由priv變量所指向的 nand_flash的各類操作函數(比如read_addr、read_data等)來實現的。
15-20行是初始化S3C2410上的 NAND FLASH控制器。前面分配的nand_flash結構還是空的,現在當然就是填滿它的各類成員了,這正是21-26行做的事情。27-30行對這塊 nand flash作了一下復位操作。最后,也是最復雜的部分,根據剛才填充的nand_flash結構,構造mtd_info結構,這由31行的 smc_insert函數調用smc_scan完成。

轉載于:https://www.cnblogs.com/hnrainll/archive/2011/05/18/2050603.html

總結

以上是生活随笔為你收集整理的S3C2410 bootloader ----VIVI阅读笔记 (转)下的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。