Using the mmu in a much simpler way (sections instead of pages) after doing
the mmu example. Not sure how this worked before it was set for an address of 0 not 0x8000
This commit is contained in:
+3
-1
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
|
||||
ARMGNU ?= arm-none-linux-gnueabi
|
||||
ARMGNU ?= arm-linux-gnueabi
|
||||
|
||||
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding
|
||||
|
||||
@@ -11,6 +11,7 @@ clean :
|
||||
rm -f *.o
|
||||
rm -f *.bin
|
||||
rm -f *.elf
|
||||
rm -f *.hex
|
||||
rm -f *.list
|
||||
|
||||
vectors.o : vectors.s
|
||||
@@ -25,6 +26,7 @@ uart.o : uart.c
|
||||
notmain.bin : memmap vectors.o uart.o notmain.o
|
||||
$(ARMGNU)-ld -T memmap vectors.o notmain.o uart.o -o notmain.elf
|
||||
$(ARMGNU)-objdump -D notmain.elf > notmain.list
|
||||
$(ARMGNU)-objcopy notmain.elf -O ihex notmain.hex
|
||||
$(ARMGNU)-objcopy notmain.elf -O binary notmain.bin
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram : ORIGIN = 0x00000000, LENGTH = 0x10000
|
||||
ram : ORIGIN = 0x00008000, LENGTH = 0x10000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
|
||||
+8
-85
@@ -13,95 +13,21 @@ extern unsigned int LDREX ( unsigned int, unsigned int );
|
||||
extern unsigned int STREX ( unsigned int, unsigned int, unsigned int );
|
||||
extern unsigned int EXTEST ( unsigned int, unsigned int, unsigned int );
|
||||
|
||||
//Need a top level entry for every 1MB section, 20 bits.
|
||||
//memory base addresses 0x100000, 0x200000, 0x300000, etc.
|
||||
//making a one to one virtual to physical map
|
||||
//virtual 0x20201234 -> 0x20201234 physical
|
||||
//
|
||||
//bits 31:20 of the virtual address index into the top level table
|
||||
//1<<((31-20)+1) 4096 entries. 0x1000 32 bit entries, 0x4000 bytes.
|
||||
//
|
||||
//Bits 31:10 of the top level table point at the course page table
|
||||
//bits 19:12 of the address index into this table.
|
||||
//1<<((19-12)+1) 256 entries, 0x100 entries 0x400 bytes per entry
|
||||
//
|
||||
//Using a course entry
|
||||
//
|
||||
//the hardware looks in the first table and gets an entry. Bits in the
|
||||
//entry determine what kind it is, course, section, super section,
|
||||
//just using course here as it doesnt save any space using the others.
|
||||
//You can put the coarse entry anywhere. Going to pack it in next to
|
||||
//the top level table. going to limit the size of the table so only
|
||||
//so many entries will be allowed
|
||||
//
|
||||
//Using small pages (4096 byte)
|
||||
//
|
||||
//bits 31:12 of the small page descriptor in the course table are the
|
||||
//physical address in memory. bits 11:0 of the physical address come
|
||||
//from the virtual address.
|
||||
|
||||
#define MMUTABLEBASE 0x00100000
|
||||
|
||||
#define MMUTABLESIZE (0x8000)
|
||||
#define MMUTABLEMASK ((MMUTABLESIZE-1)>>2)
|
||||
|
||||
#define TOP_LEVEL_WORDS (1<<((31-20)+1))
|
||||
#define COARSE_TABLE_WORDS (1<<((19-12)+1))
|
||||
#define SMALL_TABLE_WORDS (1<<((11-0)+1))
|
||||
|
||||
unsigned int nextfree;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
unsigned int next_coarse_offset ( unsigned int x )
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
mask=(~0)<<(10-2);
|
||||
mask=~mask;
|
||||
while(x&mask) x++; //lazy brute force
|
||||
return(x);
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
unsigned int add_one ( unsigned int add, unsigned int flags )
|
||||
unsigned int mmu_section ( unsigned int add, unsigned int flags )
|
||||
{
|
||||
unsigned int ra;
|
||||
unsigned int rb;
|
||||
unsigned int rc;
|
||||
|
||||
//bits 31:20 index into the top level table
|
||||
ra=add>>20;
|
||||
rc=MMUTABLEBASE+(ra<<2);
|
||||
rb=GET32(rc);
|
||||
if(rb)
|
||||
{
|
||||
//printf("Address %08X already allocated\n",add);
|
||||
hexstring(add);
|
||||
hexstring(rc);
|
||||
hexstring(rb);
|
||||
hexstring(0xBADADD);
|
||||
return(1);
|
||||
}
|
||||
add=ra<<20;
|
||||
|
||||
rb=next_coarse_offset(nextfree);
|
||||
rc=rb+COARSE_TABLE_WORDS;
|
||||
if(rc>=MMUTABLESIZE)
|
||||
{
|
||||
//printf("Not enough room\n");
|
||||
hexstring(0xBAD);
|
||||
return(1);
|
||||
}
|
||||
nextfree=rc;
|
||||
//use course page table pointer on top level table
|
||||
PUT32(MMUTABLEBASE+(ra<<2),(MMUTABLEBASE+(rb<<2))|0x00000001);
|
||||
//fill in the course page table. with small entries
|
||||
for(ra=0;ra<COARSE_TABLE_WORDS;ra++)
|
||||
{
|
||||
PUT32(MMUTABLEBASE+(rb<<2)+(ra<<2),(add+(ra<<12))|0x00000032|flags);
|
||||
}
|
||||
rb=MMUTABLEBASE|(ra<<2);
|
||||
rc=(ra<<20)|flags|2;
|
||||
PUT32(rb,rc);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
int notmain ( void )
|
||||
{
|
||||
@@ -113,15 +39,12 @@ int notmain ( void )
|
||||
|
||||
hexstring(0x12345678);
|
||||
|
||||
for(nextfree=0;nextfree<TOP_LEVEL_WORDS;nextfree++) PUT32(MMUTABLEBASE+(nextfree<<2),0);
|
||||
//nextfree=TOP_LEVEL_WORDS;
|
||||
|
||||
//ram used by the stack and the program
|
||||
if(add_one(0x00000000,0x0000|8|4)) return(1);
|
||||
if(mmu_section(0x00000000,0x0000|8|4)) return(1);
|
||||
//Memory mapped I/O used by the uart, etc, not cached
|
||||
if(add_one(0x20000000,0x0000)) return(1);
|
||||
if(add_one(0x20100000,0x0000)) return(1);
|
||||
if(add_one(0x20200000,0x0000)) return(1);
|
||||
if(mmu_section(0x20000000,0x0000)) return(1);
|
||||
if(mmu_section(0x20100000,0x0000)) return(1);
|
||||
if(mmu_section(0x20200000,0x0000)) return(1);
|
||||
|
||||
//not enabling data cache just yet.
|
||||
start_mmu(MMUTABLEBASE,0x00800001);
|
||||
|
||||
@@ -50,6 +50,7 @@ start_l1cache:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7, 0 ;@ invalidate caches
|
||||
mcr p15, 0, r0, c8, c7, 0 ;@ invalidate tlb
|
||||
mcr p15, 0, r2, c7,c10, 4 ;@ DSB ??
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
orr r0,r0,#0x1000 ;@ instruction
|
||||
orr r0,r0,#0x0004 ;@ data
|
||||
|
||||
Reference in New Issue
Block a user