00. 目录


文章目录


00. 目录01. 开发环境02. Tiny4412内存布局03. 配置MMU04. 程序示例一05. 程序示例二06. 附录

01. 开发环境


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

02. Tiny4412内存布局

【ARM】Tiny4412裸板编程之MMU(段 16M)_内存管理单元

咱们的内存是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(段 16M)_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(段 16M)_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(段 16M)_MMU 16M_04

To access the DACR, software reads or writes the CP15 registers with  <opc1> set to 0,  <CRn> set to c3,  
<CRm> set toc0, 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(段 16M)_内存管理单元_05

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;

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;
*p = 0x11223344;

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

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

//0xC2345648 --> 0x72345648
ttb[0xC23] = (0x72 << 24) | (1 << 18) | 2;

//test.bin
ttb[0x500] = (0x50 << 24) | (1 << 18) | 2;

//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;
print("*p = %#x\n", *p);

print("main end\n");

//禁用MMU
disable_mmu();

return 0;
}

执行结果

## Starting application at 0x50000000 ...
main start
*p = 0x11223344
*p = 0x11112222
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;

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*)0x70005648;
*p = 0x11223344;

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

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

//0x00005648 --> 0x70005648
ttb[0x0] = (0x70 << 24) | (1 << 18) | 2;

//test.bin
ttb[0x500] = (0x50 << 24) | (1 << 18) | 2;

//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;
print("*p = %#x\n", *p);

print("main end\n");

//禁用MMU
disable_mmu();

return 0;
}

执行结果

## Starting application at 0x50000000 ...
main start
*p = 0x11223344
*p = 0x11223344
main end
## Application terminated, rc = 0x0

06. 附录

Exynos 4412 SCP_Users Manual_Ver.0.10.00_Preliminary0.pdf