void mem_map_nor(void)
{
copy_vivi_to_ram();
mem_mapping_linear();
nor_flash_mapping();
nor_flash_remapping();
}
static void copy_vivi_to_ram(void)
{
putstr_hex("Evacuating 1MB of Flash to DRAM at 0x", VIVI_RAM_BASE);
memcpy((void *)VIVI_RAM_BASE, (void *)VIVI_ROM_BASE, VIVI_RAM_SIZE);
}
由于NORFLASH的也是可以通过地址线立即寻址的,所以读操作可以通过MEMCPY直接实现,比NAND要简单。
mem_mapping_linear(void)
static inline void mem_mapping_linear(void)
{
unsigned long pageoffset, sectionNumber;
putstr_hex("MMU table base address = 0x", (unsigned long)mmu_tlb_base);
/* 4G 康开阑 1:1肺 概俏. not cacacheable, not bufferable */
for (sectionNumber = 0; sectionNumber < 4096; sectionNumber++) {
pageoffset = (sectionNumber << 20);
*(mmu_tlb_base + (pageoffset >> 20)) = pageoffset | MMU_SECDESC;
}
/* make dram cacheable */
for (pageoffset = DRAM_BASE; pageoffset < (DRAM_BASE+DRAM_SIZE); pageoffset += SZ_1M) {
//DPRINTK(3, "Make DRAM section cacheable: 0x%08lx/n", pageoffset);
*(mmu_tlb_base + (pageoffset >> 20)) = pageoffset | MMU_SECDESC | MMU_CACHEABLE;
}
}
函数的第一部分(for 1):可以看到是从TLB的偏址0开始直到最后共4K个索引,因为每个索引对应1M的空间(sectionNumber << 20),所以它是针对整个4G范围设置映射关系的。
函数的第二部分(for 2): 可以看到它是从对应DRAM的偏址开始到DRAM结束的索引,因此它针对的是DRAM空间的映射。
nor_flash_mapping();
将FLASH_BASE(0x0)和FLASH_UNCACHED_BASE(0x10000000) 都映射到FLASH_BASE,大小为FLASH_SIZE
这就是我们可以通过基于FLASH_UNCACHED_BASE的地址来访问到nor flash的原因(linux内核下是通过ioremap来实现的),但是看代码的时候发现这个函数有明显的BUG,网上查了下,果然也有人遇到了这个问题:
static inline void nor_flash_mapping(void) //by yhn, has bug.
{
unsigned long offset, cached_addr, uncached_addr;
cached_addr = FLASH_BASE; //------------------------------bug
uncached_addr = FLASH_UNCACHED_BASE; //------------------------------bug
for (offset = 0; offset < FLASH_SIZE; offset += MMU_SECTION_SIZE) {
cached_addr += offset;
uncached_addr += offset;
*(mmu_tlb_base + (cached_addr >> 20)) = /
(cached_addr | MMU_SECDESC | MMU_CACHEABLE);
*(mmu_tlb_base + (uncached_addr >> 20)) = /
(cached_addr | MMU_SECDESC);
}
}
nor_flash_remapping(void)
因为已经将VIVI搬移到了SDRAM中,所以vivi在FLASH中的地址也映射到相应的RAM中,可以使得VIVI的读写在RAM中进行。
static inline void nor_flash_remapping(void)
{
putstr_hex("Map flash virtual section to DRAM at 0x", VIVI_RAM_BASE);
*(mmu_tlb_base + (VIVI_ROM_BASE >> 20)) = /
(VIVI_RAM_BASE | MMU_SECDESC | MMU_CACHEABLE);
}
按照从上往下的步骤实现这4个函数,后一步在前一步的基础上进行修改。完成映射操作。