00. 目录

01. 开发环境

  • 开发板:Tiny4412SDK标准版 「Tiny4412 SDK 1506」
  • 工具:「arm-linux-gcc-4.5.1」 「minicom」 「dnw」
  • 平台:Ubuntu 20.04

02. Tiny4412内存布局

【ARM】Tiny4412裸板编程之MMU(页 4K)_armv7

咱们的内存是1G,范围是0x40000000~0x8000000

在0x40000000~0x80000000, 程序示例

#include <string.h>
#include <adc.h>
#include <gpio.h>
    

void (*udelay)(unsigned int) = (void*)0x43e26480;
int (*print)(const char *format, ...) = (void*)0x43e11a2c;

extern unsigned int __bss_start;
extern unsigned int __bss_end;



int main(void)
{

    //0x40000000 ~ 0x80000000  1G
    memset((void*)&__bss_start, 0, (int)&__bss_end -(int)&__bss_start);

    print("main start\n");


    U32 *p = (void*)0x72345678;
    *p = 0x11223344;

    print("*p = %#x\n", *p);

    p = (void*)0x82345678;
    *p = 0x11112222;
    print("*p = %#x\n", *p);

    print("main end\n");

    return 0;
}

执行结果

## Starting application at 0x50000000 ...
main start
*p = 0x11223344

03. 配置MMU

3.1 使能MMU

B3.2.4 Enabling MMUs
【ARM】Tiny4412裸板编程之MMU(页 4K)_MMU_02

    .section .text
    .align 2
    .global mmu_enable
mmu_enable:

    mrc p15, 0, r0, c1, c0, 0
    orr r0, r0, #1 @将M为设置为1
    mcr p15, 0, r0, c1, c0, 0

    mov pc, lr


3.2 禁用MMU

    .section .text
    .align 2
    .global disable_mmu
disable_mmu:

    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #1 @将M为设置为0
    mcr p15, 0, r0, c1, c0, 0

    mov pc, lr

3.3 设置页表基地址

B4.1.154 TTBR0, Translation Table Base Register 0, VMSA
【ARM】Tiny4412裸板编程之MMU(页 4K)_armv7_03

访问TTBR0的方法

MRC p15, 0, <Rt>, c2, c0, 0 ; Read 32-bit TTBR0 into Rt
MCR p15, 0, <Rt>, c2, c0, 0 ; Write Rt to 32-bit TTBR0

设置TTB的基地址

    .section .text
    .align 2
    .global set_ttb
set_ttb:
    mcr p15, 0, r0, c2, c0, 0
    mov pc, lr

3.4 设置Domain访问权限

B4.1.43 DACR, Domain Access Control Register, VMSA
【ARM】Tiny4412裸板编程之MMU(页 4K)_内存管理单元_04

To access the DACR, software reads or writes the CP15 registers with  <opc1> set to 0,  
<CRn> set to c3,  <CRm> set to
c0, and  <opc2> set to 0. For example:
MRC p15, 0, <Rt>, c3, c0, 0 ; Read DACR into Rt
MCR p15, 0, <Rt>, c3, c0, 0 ; Write Rt to DACR

设置域访问权限

    .section .text
    .align 2
    .global set_domain
set_domain:
    mcr p15, 0, r0, c3, c0, 0
    mov pc, lr

04. 程序示例一

一级页表描述符格式
【ARM】Tiny4412裸板编程之MMU(页 4K)_MMU 4K_05

二级页表描述符格式
【ARM】Tiny4412裸板编程之MMU(页 4K)_MMU 4K_06

sp15.S文件内容如下

    .section .text
    .align 2
    .global get_midr
get_midr:
    MRC p15, 0, r0, c0, c0, 0 
    mov pc, lr


    .section .text
    .align 2
    .global get_ccsidr
get_ccsidr:
    MRC p15, 1, r0, c0, c0, 0
    mov pc, lr


    .section .text
    .align 2
    .global get_sctlr
get_sctlr:
    MRC p15, 0, r0, c1, c0, 0
    mov pc, lr

    .section .text
    .align 2
    .global get_id_mmfr3
get_id_mmfr3:
    MRC p15, 0, r0, c0, c1, 7
    mov pc, lr


    .section .text
    .align 2
    .global enable_mmu
enable_mmu:

    mrc p15, 0, r0, c1, c0, 0
    orr r0, r0, #1
    mcr p15, 0, r0, c1, c0, 0

    mov pc, lr


    .section .text
    .align 2
    .global disable_mmu
disable_mmu:

    mrc p15, 0, r0, c1, c0, 0
    bic r0, r0, #1
    mcr p15, 0, r0, c1, c0, 0

    mov pc, lr

    .section .text
    .align 2
    .global set_ttb
set_ttb:
    mcr p15, 0, r0, c2, c0, 0
    mov pc, lr


    .section .text
    .align 2
    .global set_domain
set_domain:
    mcr p15, 0, r0, c3, c0, 0
    mov pc, lr

test.c文件内容如下

#include <string.h>
#include <stdlib.h>
#include <adc.h>
#include <gpio.h>
    

void (*udelay)(unsigned int) = (void*)0x43e26480;
int (*print)(const char *format, ...) = (void*)0x43e11a2c;

extern unsigned int __bss_start;
extern unsigned int __bss_end;

//TTB的基地址
U32 *ttb = (void*)0x60000000;
U32 *ttb_c = (void*)0x61000000;

int main(void)
{
    int i = 0;

    //0x40000000 ~ 0x80000000  1G
    memset((void*)&__bss_start, 0, (int)&__bss_end -(int)&__bss_start);

    print("main start\n");


    U32 *p = (void*)0x72345648;
    for (i = 0; i < 100; i++)
    {
        p[i] = i; 
    }

    print("*p = %#x\n", *p);

    //清零 4K * 4Byte
    memset((void*)ttb, 0, 4096 * 4);
    memset((void*)ttb_c, 0, 256* 4);


    //0xC2345648 --> 0x72345648
    ttb[0xC23] = (int)ttb_c | 0x1;
    ttb_c[0x45] = (0x72345 << 12) | 0x2;

    //test.bin
    //ttb[0x500] = (0x50 << 24) | (1 << 18) | 2;
    ttb[0x500] = (int)ttb_c | 0x1;
    ttb_c[0x0] = (0x50000 << 12) | 0x2;



    //U-Boot.bin stack
    U32 pa;
    for (i = 0x42000000; i < 0x44000000; i += 1000000)    
    {
        pa = i >> 24;
        ttb[i >> 20] = (pa << 24) | (1 << 18) | 2;
    }

    //所有寄存器的地址
    for (i = 0x10000000; i < 0x14000000; i += 1000000)    
    {
        pa = i >> 24;
        ttb[i >> 20] = (pa << 24) | (1 << 18) | 2;
    }

    //设置TTB基地址
    set_ttb(ttb);

    //设置域访问权限
    set_domain(0xffffffff);

    //使能MMU
    enable_mmu();

    p = (void*)0xC2345648;
    for (i = 0; i < 100; i++)
    {
        print("p[%d] = %d\n", i, p[i]); 
    }

    print("main end\n");

    //禁用MMU
    disable_mmu();

    return 0;
}

执行结果

## Starting application at 0x50000000 ...
main start
*p = 0x0
p[0] = 0
p[1] = 1
p[2] = 2
p[3] = 3
p[4] = 4
p[5] = 5
p[6] = 6
p[7] = 7
p[8] = 8
p[9] = 9
p[10] = 10
p[11] = 11
p[12] = 12
p[13] = 13
p[14] = 14
p[15] = 15
p[16] = 16
p[17] = 17
p[18] = 18
p[19] = 19
p[20] = 20
p[21] = 21
p[22] = 22
p[23] = 23
p[24] = 24
p[25] = 25
p[26] = 26
p[27] = 27
p[28] = 28
p[29] = 29
p[30] = 30
p[31] = 31
p[32] = 32
p[33] = 33
p[34] = 34
p[35] = 35
p[36] = 36
p[37] = 37
p[38] = 38
p[39] = 39
p[40] = 40
p[41] = 41
p[42] = 42
p[43] = 43
p[44] = 44
p[45] = 45
p[46] = 46
p[47] = 47
p[48] = 48
p[49] = 49
p[50] = 50
p[51] = 51
p[52] = 52
p[53] = 53
p[54] = 54
p[55] = 55
p[56] = 56
p[57] = 57
p[58] = 58
p[59] = 59
p[60] = 60
p[61] = 61
p[62] = 62
p[63] = 63
p[64] = 64
p[65] = 65
p[66] = 66
p[67] = 67
p[68] = 68
p[69] = 69
p[70] = 70
p[71] = 71
p[72] = 72
p[73] = 73
p[74] = 74
p[75] = 75
p[76] = 76
p[77] = 77
p[78] = 78
p[79] = 79
p[80] = 80
p[81] = 81
p[82] = 82
p[83] = 83
p[84] = 84
p[85] = 85
p[86] = 86
p[87] = 87
p[88] = 88
p[89] = 89
p[90] = 90
p[91] = 91
p[92] = 92
p[93] = 93
p[94] = 94
p[95] = 95
p[96] = 96
p[97] = 97
p[98] = 98
p[99] = 99
main end
## Application terminated, rc = 0x0

05. 程序示例二

将0x00005648地址映射到0x70005648

test.c文件

#include <string.h>
#include <stdlib.h>
#include <adc.h>
#include <gpio.h>
    

void (*udelay)(unsigned int) = (void*)0x43e26480;
int (*print)(const char *format, ...) = (void*)0x43e11a2c;

extern unsigned int __bss_start;
extern unsigned int __bss_end;

//TTB的基地址
U32 *ttb = (void*)0x60000000;
U32 *ttb_c = (void*)0x61000000;

int main(void)
{
    int i = 0;

    //0x40000000 ~ 0x80000000  1G
    memset((void*)&__bss_start, 0, (int)&__bss_end -(int)&__bss_start);

    print("main start\n");


    U32 *p = (void*)0x72345648;
    for (i = 0; i < 100; i++)
    {
        p[i] = i; 
    }

    print("*p = %#x\n", *p);

    //清零 4K * 4Byte
    memset((void*)ttb, 0, 4096 * 4);
    memset((void*)ttb_c, 0, 256* 4);


    //0x5648 --> 0x72345648
    ttb[0x0] = (int)ttb_c | 0x1;
    ttb_c[0x5] = (0x72345 << 12) | 0x2;

    //test.bin
    //ttb[0x500] = (0x50 << 24) | (1 << 18) | 2;
    ttb[0x500] = (int)ttb_c | 0x1;
    ttb_c[0x0] = (0x50000 << 12) | 0x2;



    //U-Boot.bin stack
    U32 pa;
    for (i = 0x42000000; i < 0x44000000; i += 1000000)    
    {
        pa = i >> 24;
        ttb[i >> 20] = (pa << 24) | (1 << 18) | 2;
    }

    //所有寄存器的地址
    for (i = 0x10000000; i < 0x14000000; i += 1000000)    
    {
        pa = i >> 24;
        ttb[i >> 20] = (pa << 24) | (1 << 18) | 2;
    }

    //设置TTB基地址
    set_ttb(ttb);

    //设置域访问权限
    set_domain(0xffffffff);

    //使能MMU
    enable_mmu();

    p = (void*)0x5648;
    for (i = 0; i < 100; i++)
    {
        print("p[%d] = %d\n", i, p[i]); 
    }

    print("main end\n");

    //禁用MMU
    disable_mmu();

    return 0;
}

执行结果

## Starting application at 0x50000000 ...
main start
*p = 0x0
p[0] = 0
p[1] = 1
p[2] = 2
p[3] = 3
p[4] = 4
p[5] = 5
p[6] = 6
p[7] = 7
p[8] = 8
p[9] = 9
p[10] = 10
p[11] = 11
p[12] = 12
p[13] = 13
p[14] = 14
p[15] = 15
p[16] = 16
p[17] = 17
p[18] = 18
p[19] = 19
p[20] = 20
p[21] = 21
p[22] = 22
p[23] = 23
p[24] = 24
p[25] = 25
p[26] = 26
p[27] = 27
p[28] = 28
p[29] = 29
p[30] = 30
p[31] = 31
p[32] = 32
p[33] = 33
p[34] = 34
p[35] = 35
p[36] = 36
p[37] = 37
p[38] = 38
p[39] = 39
p[40] = 40
p[41] = 41
p[42] = 42
p[43] = 43
p[44] = 44
p[45] = 45
p[46] = 46
p[47] = 47
p[48] = 48
p[49] = 49
p[50] = 50
p[51] = 51
p[52] = 52
p[53] = 53
p[54] = 54
p[55] = 55
p[56] = 56
p[57] = 57
p[58] = 58
p[59] = 59
p[60] = 60
p[61] = 61
p[62] = 62
p[63] = 63
p[64] = 64
p[65] = 65
p[66] = 66
p[67] = 67
p[68] = 68
p[69] = 69
p[70] = 70
p[71] = 71
p[72] = 72
p[73] = 73
p[74] = 74
p[75] = 75
p[76] = 76
p[77] = 77
p[78] = 78
p[79] = 79
p[80] = 80
p[81] = 81
p[82] = 82
p[83] = 83
p[84] = 84
p[85] = 85
p[86] = 86
p[87] = 87
p[88] = 88
p[89] = 89
p[90] = 90
p[91] = 91
p[92] = 92
p[93] = 93
p[94] = 94
p[95] = 95
p[96] = 96
p[97] = 97
p[98] = 98
p[99] = 99
main end
## Application terminated, rc = 0x0

06. 附录

Exynos 4412 SCP_Users Manual_Ver.0.10.00_Preliminary0.pdf