2014-12-09 8 views
2

요즘 나는 MMU를 다루기 위해 몇 가지 베어 메탈 코드를 작성하려고합니다. 시도한 후에도 여전히 제대로 작동하지 않습니다. 직렬 콘솔로 디버깅 할 수 없으며 D-STREAM과 같은 값 비싼 디버거가 없기 때문에 여기에 코드를 붙여 도움을 요청할 수 있습니다. 나는 거머리가되고 싶지 않지만, 내가 제공 할 수있는 정보가 무엇인지 모르겠다.ARM Cortex-A8에서 MMU를 활성화 할 때의 문제점. CPU는 S5PV210입니다.

내 CPU는 S5PV210 난 그냥 그냥 "가상 주소 == 물리적 주소" 코드

"ldr pc, =0x30000000\n" 
후 의미 플랫 메모리 매핑, 을하고 싶은 무엇 코어 텍스 A8 아키텍처 을 기반으로

은 플래시 LED 프로그램입니다. "enable_mmu"이 라인이

"orr r0, r0, #0x0001\n"   /* .... .... .... ...1 Enable MMU */ 

내 플래시가 주도 주석이 프로그램이 잘 작동한다면 내가 그것을 주석을 제거하면, 플래시가 작동을 중지했다. 여기 당신의 페이지 테이블 초기화 코드를 잘 것 같다 전체 프로그램

#define ttl_base 0x2F000000 
#define MMU_DES_FULL_ACESS (3<<10) 
#define MMU_DES_DOMAIN (0<<5) 
#define MMU_DES_EXECUTE_NEVER (0<<4) 
#define MMU_DES_CACHEABLE (1<<3) 
#define MMU_DES_BUFFERABLE (1<<2) 
#define MMU_DES_SECTION (2) 
#define MMU_DES_ATTRIBUTE (MMU_DES_SECTION|MMU_DES_BUFFERABLE|MMU_DES_CACHEABLE|MMU_DES_EXECUTE_NEVER|MMU_DES_DOMAIN|MMU_DES_FULL_ACESS) 
void init_mmu() 
{ 
    //Create Translation Table for a flat map (Vitual Address == Physical Address) 
    u32 virtualaddr,phyaddr; 
    u32 *mmu_tlb_base=(u32 *)ttl_base; 

    virtualaddr = 0x0; 
    phyaddr = 0x0; 
    while(1) 
    { 
     *(mmu_tlb_base + (virtualaddr>>20)) = (phyaddr & 0xFFF00000) | (MMU_DES_ATTRIBUTE); //map 0x0x30000000-0x30100000 to 0xB0000000-0xB0100000 
     virtualaddr+=0x100000; 
     phyaddr+=0x100000; 
     if (phyaddr==0x00000000) 
     { 
      break; 
     } 
    } 
} 

void enable_mmu() 
{ 
    __asm__(
     "mrc p15, 0, r0, c1, c0, 0\n" 
     "bic r0, r0, #0x3000\n" 
     "mcr p15, 0, r0, c1, c0, 0\n" /* Disable Insturection cache */ 

     "mov r0, #0\n" 
     "mcr p15, 0, r0, c7, c5, 0\n" /*Instruction cache invalidate all*/ 
     "mcr p15, 0, r0, c7, c5, 6\n" /*branch predictor invalidate all*/ 
     "mcr p15, 0, r0, c8, c7, 0\n" /* Invalidate data and instruction TLB */ 

     /*Invalidate entire Data cache*/ 
     /*Start*/ 
     "MRC p15, 1, r0, c0, c0, 0\n" /* Read Cache Size ID */ 
     "LDR r3, =0x1ff\n" 
     "AND r0, r3, r0, LSR #13\n" /* r0 = no. of sets - 1 */ 
     "MOV r1, #0\n" /* r1 = way counter way_loop */ 
     "way_loop:\n" 
     "MOV r3, #0\n" /* r3 = set counter set_loop */ 
     "set_loop:\n" 
     "MOV r2, r1, LSL #30\n" /* */ 
     "ORR r2, r3, LSL #5\n" /* r2 = set/way cache operation format */ 
     "MCR p15, 0, r2, c7, c6, 2\n" /* Invalidate line described by r2 */ 
     "ADD r3, r3, #1\n" /* Increment set counter */ 
     "CMP r0, r3\n" /* Last set reached yet? */ 
     "BGT set_loop\n" /* if not, iterate set_loop */ 
     "ADD r1, r1, #1\n" /* else, next */ 
     "CMP r1, #4\n" /* Last way reached yet? */ 
     "BNE way_loop\n" /* if not, iterate way_loop */ 
     /*End*/ 

     /*Data and Instruction barrier*/ 
     "dsb\n" 
     "isb\n" 


     "mov r0, #0\n" 
     "mcr p15, 0, r0, c2, c0, 2\n" /*Clear L2 Translation Table Entry*/ 

     "mov r4, #0x2F000000\n" 
     "mcr p15, 0, r4, c2, c0, 0\n" /*Write L1 Translation Table Entry*/ 

     "mvn r0, #0\n"     
     "mcr p15, 0, r0, c3, c0, 0\n" /*Write 0xFFFFFFFF to Domain Access Register, which means no permission check*/ 

     "mrc p15, 0, r0, c1, c0, 0\n" /* Read SCTLR */ 
              /* .RVI ..RS B... .CAM */ 
     "bic r0, r0, #0x3000\n"   /* ..11 .... .... .... Clear bit V、bit I */ 
     "bic r0, r0, #0x0087\n"   /* .... .... 1... .111 Clear bit B/C/A/M */ 


     "orr r0, r0, #0x0002\n"   /* .... .... .... ..1. Enable Aligment Check */ 
     "orr r0, r0, #0x0004\n"   /* .... .... .... .1.. Enable Data Caches */ 
     "orr r0, r0, #0x1000\n"   /* ...1 .... .... .... Enable Instruction Caches */ 
     "orr r0, r0, #0x0800\n"   /* .... 1... .... .... Enble brach prediction */ 
     "orr r0, r0, #0x0001\n"   /* .... .... .... ...1 Enable MMU */ 

     "mcr p15, 0, r0, c1, c0, 0\n" /* Write back to SCTLR */ 
     "ldr sp, =0x3F000000\n" 
     "ldr pc, =0x30000000\n" 
     "loop:\n" 
     "b loop\n" 
    ); 
} 
+0

컴파일러가 r0-r3에 'ttb'를 넣지 않았다는 것을 어떻게 알 수 있습니까? 하드 코딩 된 레지스터와 clobbers가있는 큰 인라인 asm은 일반적으로 매우 나쁜 것입니다. – Notlikethat

+0

@ Notlikethat 당신 말이 맞아요. 하지만 "void enable_mmu (void) __ attribute __ ((naked));"라고 선언하더라도. " 그리고 지역 변수를 사용하지 마십시오. 문제는 여전히 일어난다. – demonguy

+0

naked는 함수 프롤로그 및 에필로그에만 영향을 미칩니다. 물론 여기서는 관련이 없습니다. 물론 컴파일러에게 호출 수신자가 저장 한 레지스터를 지우는 것은 아닙니다. 방금 컴파일을 시도했는데, gcc가 rt에'ttb '를 넣었으므로 그 파일도 잘 쓰레기로 처리 될 것입니다. 나는 코드를 사소한 부분으로 업데이트하는 것을 권장한다 - 많은 asm은 아마 .S 파일에 속할 것이다. – Notlikethat

답변

0

입니다. 하지만 MMU_DES_ATTRIBUTE을 제공해야합니다. 나는 속성에 뭔가 문제가 있다고 생각한다.

+0

죄송합니다. 붙여 넣는 것을 잊지 마십시오. – demonguy

+0

내 속성이 올바른지 확인할 수 있습니다. 원래 게시물을 업데이트했습니다. – demonguy