S3C2440之裸机之C语言MMU

虚拟机环境:Oracle VM VirtualBox
Linux系统:ubuntu_14.04.6
交叉编译工具:[100ask分享的所有文件](https://eyun.baidu.com/s/3b1UtLc)
100ask分享的所有文件 > 002_JZ2440资料光盘_20180516(免费) > 资料光盘 > A盘 > tools.zip > arm-linux-gcc-4.3.2.tar.bz2
gcc-3.4.5-glibc-2.3.6/bin

第一步:查看原理图

left middle right
nLED4 nLED2 nLED1
GPF6 GPF5 GPF4

输出低电平点亮LED灯
输出高电平熄灭LED灯

第二步:查看芯片手册

寄存器 地址 配置
BWSCON 0x48000000 0x22011110
BANKCON0 0x48000004 0x00000700
BANKCON1 0x48000008 0x00000700
BANKCON2 0x4800000C 0x00000700
BANKCON3 0x48000010 0x00000700
BANKCON4 0x48000014 0x00000700
BANKCON5 0x48000018 0x00000700
BANKCON6 0x4800001C 0x00018005
BANKCON7 0x48000020 0x00018005
REFRESH 0x48000024 0x008C07A3
BANKSIZE 0x48000028 0x000000B1
MRSRB6 0x4800002C 0x00000030
MRSRB7 0x48000030 0x00000030

第三步:编写程序
head.S:

.text
.global _start

_start:
	ldr sp,=4096
	bl disable_watch_dog
	bl memsetup
	bl copy_2th_to_sdram
	bl create_page_table
	bl mmu_init
	ldr sp,=0xB4000000
	ldr pc,=0xB0004000

halt_loop:
	b halt_loop

init.c:

#define WTCON	(*(volatile unsigned long *)0x53000000)
#define MEM_CTL_BASE	0x48000000

void disable_watch_dog(void)
{
	WTCON = 0;
}

void memsetup(void)
{
	unsigned long const mem_cfg_val[] = {
		0x22011110,
		0x00000700,
		0x00000700,
		0x00000700,

		0x00000700,
		0x00000700,
		0x00000700,
		
		0x00018005,
		0x00018005,

		0x008C07A3,
		0x000000B1,
		0x00000030,
		0x00000030,
	};

	int i = 0;
	volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

	for (; i < 13; i ++)
		p[i] = mem_cfg_val[i];
}

void copy_2th_to_sdram(void)
{
	unsigned int *pdwSrc = (unsigned int *)2048;
	unsigned int *pdwDest = (unsigned int *)0x30004000;

	while (pdwSrc < (unsigned int *)4096) {
		*pdwDest = *pdwSrc;
		pdwDest ++;
		pdwSrc ++;
	}
}

void create_page_table(void)
{
#define MMU_FULL_ACCESS	(3<<10)
#define MMU_DOMAIN		(0<<5)
#define MMU_SPECIAL		(1<<4)
#define MMU_CACHEABLE	(1<<3)
#define MMU_BUFFERABLE	(1<<2)
#define MMU_SECTION		(2)

#define MMU_SECDESC		(MMU_FULL_ACCESS|MMU_DOMAIN|MMU_SPECIAL|MMU_SECTION)
#define MMU_SECDESC_WB	(MMU_FULL_ACCESS|MMU_DOMAIN|MMU_SPECIAL|MMU_CACHEABLE|MMU_BUFFERABLE|MMU_SECTION)

#define MMU_SECTION_SIZE	0x00100000

	unsigned long virtual_addr, physical_addr;
	unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;

	virtual_addr = 0;
	physical_addr = 0;

	*(mmu_tlb_base + (virtual_addr >> 20)) = (physical_addr & 0xFFF00000) | MMU_SECDESC_WB;
	
	virtual_addr = 0xA0000000;
	physical_addr = 0x56000000;
	
	*(mmu_tlb_base + (virtual_addr >> 20)) = (physical_addr & 0xFFF00000) | MMU_SECDESC;

	virtual_addr = 0xB0000000;
	physical_addr = 0x30000000;

	while (virtual_addr < 0xB4000000) {
		*(mmu_tlb_base + (virtual_addr >> 20)) = (physical_addr & 0xFFF00000) | MMU_SECDESC_WB;

		virtual_addr += 0x100000;
		physical_addr += 0x100000;
	}
}

void mmu_init(void)
{
	unsigned long ttb = 0x30000000;

__asm__(
	"mov r0, #0\n"
	"mcr p15, 0, r0, c7, c7, 0\n"

	"mcr p15, 0, r0, c7, c10, 4\n"
	"mcr p15, 0, r0, c8, c7, 0\n"

	"mov r4, %0\n"
	"mcr p15, 0, r4, c2, c0, 0\n"

	"mvn r0, #0\n"
	"mcr p15, 0, r0, c3, c0, 0\n"

	"mrc p15, 0, r0, c1, c0, 0\n"

	"bic r0, r0, #0x3000\n"
	"bic r0, r0, #0x0300\n"
	"bic r0, r0, #0x0087\n"

	"orr r0, r0, #0x0002\n"
	"orr r0, r0, #0x0004\n"
	"orr r0, r0, #0x1000\n"
	"orr r0, r0, #0x0001\n"

	"mcr p15, 0, r0, c1, c0, 0\n"
	:
	: "r" (ttb));
}

leds.c:

#define GPFCON (*(volatile unsigned long *)0xA0000050)
#define GPFDAT (*(volatile unsigned long *)0xA0000054)

static inline void wait(unsigned long dly)
{
	for (; dly > 0; dly --);
}

int main(void)
{
	unsigned long i = 0;

	GPFCON = 0x00001500;
	GPFDAT = 0x00000070;

	while (1) {
		wait(300000);
		GPFDAT = (~(i<<4));
		if (++ i == 8)
			i = 0;
	}

	return 0;
}

第四步:编写链接脚本和makefile
mmu.lds:

SECTIONS {
	first	0x00000000 : { head.o init.o }
	second	0xB0004000 : AT(2048) { leds.o }
}

makefile:

ARM_LINUX_XXX=/home/xlbtlmy/Desktop/ARM_Linux/gcc-3.4.5-glibc-2.3.6/bin

CC=$(ARM_LINUX_XXX)/arm-linux-gcc
LD=$(ARM_LINUX_XXX)/arm-linux-ld
OBJCOPY=$(ARM_LINUX_XXX)/arm-linux-objcopy
OBJDUMP=$(ARM_LINUX_XXX)/arm-linux-objdump
TARGET=$(OPT)
LDS=$(shell ls *.lds)

src_c=$(shell ls *.c)
objs_c=$(patsubst %.c,%.o,$(src_c))

src_s=$(shell ls *.S)
objs_s=$(patsubst %.S,%.o,$(src_s))

objs=$(objs_c) $(objs_s)

BIN=$(TARGET).bin
ELF=$(TARGET).elf
DIS=$(TARGET).dis

$(BIN):$(objs)
	$(LD) -T$(LDS) $^ -o $(ELF)
	$(OBJCOPY) -O binary -S $(ELF) $(BIN)
	$(OBJDUMP) -D -m arm $(ELF) > $(DIS)

%.o:%.c
	$(CC) -Wall -O2 -c -o $@ $<

%.o:%.S
	$(CC) -Wall -O2 -c -o $@ $<

.PHONY:clean
clean:
	rm -f *.o *.bin *.elf *.dis

make OPT=leds

第五步:烧录运行
eop.bat:

@echo off

:JTAG(0:OpenJTAG 1:DongleJTAG 2:Wiggler)
SET JTAG=0
:CPU(0:S3C2410 1:S3C2440 2:S3C6410)
SET CPU=1
:Flash(0:Nand 1:Nor)
SET Flash=0
:Access(0:Write 1:Read)
SET Access=0
:Offset()
SET Offset=0
:File()
SET File=leds.bin

oflash %JTAG% %CPU% %Flash% %Access% %Offset% %File%

pause

第五步:观察实验现象
流水灯,速度较快

发布了50 篇原创文章 · 获赞 14 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/u011958166/article/details/95166712