寄存器TCFG0由三部分组成,prescaler0,prescaler1,deadzone和reserve四部分,前三部分分别对应 TCFG0_PRE0、TCFG0_PRE1、TCFG0_DZONE,TCFG0_PRE0(0)实际值为0x00,TCFG0_PRE1(15)实际值为0x0f00,而TCFG0_DZONE(0)实际值为 0x000000。实际中,vivi并未使用定时器,这个函数就可以忽略。set_gpios()用于选择GPA至GPH端口各引脚的功能及是否使用各引脚的内部上拉电阻,并设置外部中断源寄存器EXTINT0-2(vivi中未使用外部中断)。
1 void set_gpios(void)
2 {
3 GPACON = vGPACON;
4 GPBCON = vGPBCON;
5 GPBUP = vGPBUP;
6 GPCCON = vGPCCON;
7 GPCUP = vGPCUP;
8 GPDCON = vGPDCON;
9 GPDUP = vGPDUP;
10 GPECON = vGPECON;
11 GPEUP = vGPEUP;
12 GPFCON = vGPFCON;
13 GPFUP = vGPFUP;
14 GPGCON = vGPGCON;
15 GPGUP = vGPGUP;
16 GPHCON = vGPHCON;
17 GPHUP = vGPHUP;
18 EXTINT0 = vEXTINT0;
19 EXTINT1 = vEXTINT1;
20 EXTINT2 = vEXTINT2;
21 }
以第三行为例,vGPACON的值为0x007fffff,查找s3c2410用户手册可知,该参数将GPACON的23位全部置1。各位功能需察看s3c2410用户手册
3、Step 3:建立页表和启动MMU
mem_map_init();
mmu_init();
mem_map_init函数用于建立页表,vivi使用段式页表,只需要一级页表。它调用3个函数,代码在arch/s3c2410/mmu.c中:
[main(int argc, char *argv[]) > mem_map_init(void)]
1 void mem_map_init(void)
2 {
3 #ifdef CONFIG_S3C2410_NAND_BOOT
/*CONFIG_S3C2410_NAND_BOOT = y ,在文件include/autoconf.h中定义*/
4 mem_map_nand_boot();
/* 最终调用mem_mepping_linear, 建立页表 */
5 #else
6 mem_map_nor();
7 #endif
8 cache_clean_invalidate();/* 清空cache,使无效cache */
9 tlb_invalidate(); /* 使无效快表TLB */
10 }
第9、 10行的两个函数可以不用管它,他们做的事情在下面的mmu_init函数里又重复了一遍。对于本开发板,在.config中定义了 CONFIG_S3C2410_NAND_BOOT。mem_map_nand_boot()函数调用mem_mapping_linear()函数来最终完成建立页表的工作。页表存放在SDRAM物理地址0x33dfc000开始处,共16K:一个页表项4字节,共有4096个页表项;每个页表项对应 1M地址空间,共4G。mem_map_init先将4G虚拟地址映射到相同的物理地址上,NCNB(不使用cache,不使用write buffer)——这样,对寄存器的操作跟未启动MMU时是一样的;再将SDRAM对应的64M空间的页表项修改为使用cache。 mem_mapping_linear函数的代码在arch/s3c2410/mmu.c中:
[main(int argc, char *argv[]) > mem_map_init(void) > mem_map_nand_boot( ) > mem_mapping_linear(void)]
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 }
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 }
评论
查看更多