<< REDBOOT 소스 분석 >>
시스템이 시작되는 곳
arm.ld 소스보기
... ... ... 생략 ... ... ...
Entry(reset_vector);
//reset_vector부터 시작한다.
... ... ... 생략 ... ... ...
exception handler 중 reset_vector
vector.S 소스보기
... ... ... 생략 ... ... ...
reset_vector:
PLATFORM_SETUP1
//platform에 관한 setup을 한다.
//여기서는 smdk2410에 맞추어 setting한다.
... ... ... 생략 ... ... ...
platform마다의 다른 설정(arm9/smdk2410에 맞게 설정)
hardware에 dependent하다.
Hal_platform_setup.h 소스보기
... ... ... 생략 ... ... ...
#define PLATFORM_SETUP1 _platform_setup1
//reset_vector에서 호출한 macro 선언부
... ... ... 생략 ... ... ...
.macro RAW_LED_MACRO x
ldr r0,=GPFDAT
ldr r1,[r0]
bic r1,r1,#(0xf<<4)
orr r1,r1,#((0xf & ~(\x))<<4)
str r1, [r0]
.endm
//GPFDAT: 데이터를 읽거나 쓰기 위한 register(0x56000054)
//[4:7]에 상태를 설정한다. (불을 켜고 싶으면 clear, 불을 끄고 싶으면 set)
// Configure GPF[4:7] as Output & pull-up turned off
//LED는 포트 G그룹(GPF)의 4bit에서 7bit까지에 연결되어 있다. ([0:3]은 외부 인터럽트)
.macro RAW_LED_PORT_INIT_MACRO
ldr r0,=GPFUP
ldr r1,[r0]
orr r1,r1,#((1<<7)|(1<<6)|(1<<5)|(1<<4))
str r1,[r0]
//GPFUP: pull-up register사용여부(0x56000058)
//LED에서는 상위 4bit(GPF[4:7])만 사용 설정
RAW_LED_MACRO 0
ldr r0,=GPFCON
ldr r1,[r0]
orr r1,r1,#((1<<14)|(1<<12)|(1<<10)|(1<<8))
str r1,[r0]
.endm
//GPFCON: 포트 핀 기능 설정 (00: input, 01: output) (register addr: 0x56000050)
//0101010100000000 ([0:3]은 input, [4:7]은 output)으로 설정
// platform을 위한 실제 startup코드가 여기서 시작된다.
.macro _platform_setup1
#ifndef CYG_HAL_STARTUP_RAM
ldr r0,=WTCON // watch dog disable
ldr r1,=0x0
str r1,[r0]
/*
- WDT(watch dog timer): 시스템에 문제가 생길 경우 자동 reset을 시켜준다.
- WDT제어 register(WTCON)에 0을 설정하여, reset 되는 도중에 또 다시 reset이 발생하지 않도록 disable시켜준다.
- default는 enable이다.
- WTCON의 주소는 0x53000000이다.
*/
#endif
RAW_LED_PORT_INIT_MACRO
#ifndef CYG_HAL_STARTUP_RAM
ldr r0,=INTMSK
ldr r1,=0xffffffff // all interrupt disable
str r1,[r0]
ldr r0,=INTSUBMSK
ldr r1,=0x7ff // all sub interrupt disable
str r1,[r0]
//모든 interrupt에 masking함으로써 interrupt가 들어올 수 없게 한다.
//1이면 masking, 0이면 masking해제
RAW_LED_MACRO 1
//코프로세서 명령어 mrc와 mcr을 사용하는 부분.
//코프로세서 명령어는 각 platform마다 다르기 때문에 datasheet를 참조하여 프로그래밍 한다.
// Disable and clear caches
mrc p15,0,r0,c1,c0,0
bic r0,r0,#0x1000 // disable ICache
bic r0,r0,#0x000f // disable DCache, write buffer,
// MMU and alignment faults
mcr p15,0,r0,c1,c0,0
nop
nop
mov r0,#0
mcr p15,0,r0,c7,c6,0 // clear data cache
#if 0
mrc p15,0,r0,c15,c1,0 // disable streaming
orr r0,r0,#0x80
mcr p15,0,r0,c15,c1,0
#endif
// To reduce PLL lock time, adjust the LOCKTIME register.
ldr r0,=LOCKTIME
ldr r1,=0xffffff
str r1,[r0]
/*
- PLL(Phase Locked Loop): 출력 신호 주파수를 일정하게 유지, 칩 외부의 낮은 주파수를 증폭. (초기화 과정에서 PLL을 설정한다)
- Lock Time: PLL에 의해 주파수가 변하는 동안 시스템에 공급되는 FCLK를 중단하는 시간.
- LOCKTIME(Lock Time register): Lock Time을 설정
- lock time이 필요 이상으로 크게 설정되면 시스템 성능이 떨어지지만, 변화하는 중간 주파수의 클락 공급을 막아야 한다.
*/
//clock 비율을 설정한다.
// We must set ratios, set memctl, then change FCLK.
ldr r0,=CLKDIVN // Set ratios 1:2:4 for FCLK:HCLK:PCLK
ldr r1,=(3)
str r1,[r0]
/*
- FCLK: cpu를 위한 clock
- HCLK: AHB bus에서 사용. memory controller, interrupt controller, LCD controller등의 제어
- PCLK: APB bus에서 사용. WDT, PWM timer, MMC interface, ADC, UART, GPIO, RTC같은 주변장치에 의해 사용됨.
- 3(10)으로 설정할 경우 clock 비율이 FCLK:HCLK:PCLK = 1:2:4로 설정되며, 주기는 FCLK가 가장 짧고, PCLK보다 4배 빨리 튄다.
- CLKDIVN의 1bit가 0이면 hclk = fclk, 1이면 hclk = fclk/2
- CLKDIVN의 0bit가 0이면 pclk = hclk, 1이면 pclk = hclk/2
→ 그러므로 "10"으로 설정하면 1:2:4가 된다.
*/
// MMU_SetAsyncBusMode //Must select, since we're setting HDIVN=1
#define R1_iA (1<<31)
#define R1_nF (1<<30)
mrc p15,0,r0,c1,c0,0
orr r0,r0,#(R1_nF|R1_iA)
mcr p15,0,r0,c1,c0,0
//memory bank initialize
// Set memory control registers
adr r0,1f //label '1'의 상대주소를 저장한다.
ldr r1,=BWSCON // BWSCON Address
add r2, r0, #52 // End address of SMRDATA //13개의 제어 register * 4 = 52
//r2는 loop의 끝지점을 저장하고 있게 된다.
//adr명령어는 주소값을 register에 저장하는 의사명령어이다.
//BWSCON: memory control (bus width & wait status)
//SMRDATA: set memory control register (BANCON0~7, RAM제어 관련 register들이 포함된다)
0:
ldr r3, [r0], #4 // r0가 가리키는 곳의 내용을 r3로 넣고 r0의 주소를 4만큼 증가
str r3, [r1], #4 // r3의 내용을 r1이 가리키는 곳으로 놓고 r1을 4만큼 증가
cmp r2, r0 //loop가 끝났는지 검사
bne 0b //label '0'으로 jmp (= loop)
b 2f //loop가 끝나면 label '2'로 jmp
1:
// Memory configuration should be optimized for best performance
// The following parameter is not optimized.
// Memory access cycle parameter strategy
// 1) The memory settings is safe parameters even at HCLK=75Mhz.
// 2) SDRAM refresh period is for HCLK=75Mhz.
//여기서부터가 SMRDATA의 진짜 데이타
.long (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.long ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) //GCS0
.long ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) //GCS1
.long ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) //GCS2
.long ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) //GCS3
.long ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) //GCS4
.long ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) //GCS5
.long ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) //GCS6
.long ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) //GCS7
.long ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.long 0x32 // SCLK power saving mode, BANKSIZE 128M/128M
.long 0x30 // MRSR6 CL=3clk
.long 0x30 // MRSR7
// .long 0x20 // MRSR6 CL=2clk
// .long 0x20 // MRSR7
2:
RAW_LED_MACRO 2
// Configure MPLL
ldr r0,=MPLLCON
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) // Fin=12MHz,Fout=50MHz
str r1,[r0]
/*MPLL clock설정
- MPLL은 FCLK, HCLK, PCLK를 위한 PLL이다.
- 각 platform에 맞는 MDIV, PDIV, SDIV값이 존재한다. 이것을 각각 [19:12], [9:4], [1:0] 비트에 설정한다.
- MPLLCON register를 설정해야만 설정된 값에 의해 PLL이 변하고 lock time이후에 안정된 주파수가 공급된다.
*/
#endif /* !CYG_HAL_STARTUP_RAM */
// Set up a stack [for calling C code]
ldr r1,=__startup_stack //vecter.S의 맨 마지막
ldr r2,=SMDK2410_SDRAM_PHYS_BASE //0x30000000 (SDRAM의 base address)
orr sp,r1,r2
// Create MMU tables
RAW_LED_MACRO 3
bl hal_mmu_init //hal_mmu_init 호출 → Smdk2410_misc.c
RAW_LED_MACRO 4
// Enable MMU
ldr r2,=10f
#ifdef CYG_HAL_STARTUP_ROMRAM
ldr r1,=__exception_handlers
ldr r9,=0x80000000
sub r1,r2,r1
add r2,r9,r1 // r9 has ROM offset
#endif
ldr r1,=MMU_Control_Init|MMU_Control_M
mcr MMU_CP,0,r1,MMU_Control,c0
mov pc,r2 /* Change address spaces */
nop
nop
nop
10:
RAW_LED_MACRO 5
#ifdef CYG_HAL_STARTUP_ROMRAM
mov r0,r9 // Relocate FLASH/ROM to RAM
ldr r1,=__exception_handlers // ram base & length //RAM base addr. 0x0번지
ldr r2,=__rom_data_end //ROM의 끝 (length 지정 - loop의 끝을 위해)
//loop을 돌면서 ROM → RAM copy
20: ldr r3,[r0],#4
str r3,[r1],#4
cmp r1,r2
bne 20b
ldr r0,=30f
mov pc,r0
nop
nop
nop
nop
30:
#endif
RAW_LED_MACRO 6
.endm
#else // defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
#define PLATFORM_SETUP1
#endif
//-----------------------------------------------------------------------------
// end of hal_platform_setup.h
#endif // CYGONCE_HAL_PLATFORM_SETUP_H
memory management unit 초기화 및 TTB, virtual memory 설정
Smdk2410_misc.c 소스보기
... ... ... 생략 ... ... ...
void
hal_mmu_init(void)
{
unsigned long ttb_base = SMDK2410_SDRAM_PHYS_BASE + 0x4000;
//translation table base 설정
unsigned long i;
// Set the TTB register (c2)
asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/);
// Set the Domain Access Control Register (c3) - 16개까지 가능
// Domain: 섹션이나 개별 접근 권한을 가지는 페이지들의 그룹. 동일한 변환테이블을 가짐.
i = ARM_ACCESS_TYPE_MANAGER(0) |
ARM_ACCESS_TYPE_NO_ACCESS(1) |
ARM_ACCESS_TYPE_NO_ACCESS(2) |
ARM_ACCESS_TYPE_NO_ACCESS(3) |
ARM_ACCESS_TYPE_NO_ACCESS(4) |
ARM_ACCESS_TYPE_NO_ACCESS(5) |
ARM_ACCESS_TYPE_NO_ACCESS(6) |
ARM_ACCESS_TYPE_NO_ACCESS(7) |
ARM_ACCESS_TYPE_NO_ACCESS(8) |
ARM_ACCESS_TYPE_NO_ACCESS(9) |
ARM_ACCESS_TYPE_NO_ACCESS(10) |
ARM_ACCESS_TYPE_NO_ACCESS(11) |
ARM_ACCESS_TYPE_NO_ACCESS(12) |
ARM_ACCESS_TYPE_NO_ACCESS(13) |
ARM_ACCESS_TYPE_NO_ACCESS(14) |
ARM_ACCESS_TYPE_NO_ACCESS(15);
asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/);
// First clear all TT entries - ie Set them to Faulting
memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
//ARM_FIRST_LEVEL_PAGE_TABLE_SIZE = 0x4000 즉, ttb_base부터 0x4000만큼 0으로 clear
//X_ARM_MMU_SECTION 메크로 인자값
//(physical addr, virtual addr, size, cached, bufferd, access perm)
//다음은 phsycal - virtual의 연결이 이루어지는 코드이다.
X_ARM_MMU_SECTION(0x000, 0x800, 2, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // Flash
X_ARM_MMU_SECTION(0x300, 0x000, 64, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SDRAM
X_ARM_MMU_SECTION(0x400, 0x400, 1, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SRAM
X_ARM_MMU_SECTION(0x480, 0x480, 512, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SFRs
X_ARM_MMU_SECTION(0x300, 0x300, 64, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // Raw SDRAM
}
void
hal_mmu_init(void)
{
unsigned long ttb_base = SMDK2410_SDRAM_PHYS_BASE + 0x4000;
//translation table base 설정
unsigned long i;
// Set the TTB register (c2)
asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/);
// Set the Domain Access Control Register (c3) - 16개까지 가능
// Domain: 섹션이나 개별 접근 권한을 가지는 페이지들의 그룹. 동일한 변환테이블을 가짐.
i = ARM_ACCESS_TYPE_MANAGER(0) |
ARM_ACCESS_TYPE_NO_ACCESS(1) |
ARM_ACCESS_TYPE_NO_ACCESS(2) |
ARM_ACCESS_TYPE_NO_ACCESS(3) |
ARM_ACCESS_TYPE_NO_ACCESS(4) |
ARM_ACCESS_TYPE_NO_ACCESS(5) |
ARM_ACCESS_TYPE_NO_ACCESS(6) |
ARM_ACCESS_TYPE_NO_ACCESS(7) |
ARM_ACCESS_TYPE_NO_ACCESS(8) |
ARM_ACCESS_TYPE_NO_ACCESS(9) |
ARM_ACCESS_TYPE_NO_ACCESS(10) |
ARM_ACCESS_TYPE_NO_ACCESS(11) |
ARM_ACCESS_TYPE_NO_ACCESS(12) |
ARM_ACCESS_TYPE_NO_ACCESS(13) |
ARM_ACCESS_TYPE_NO_ACCESS(14) |
ARM_ACCESS_TYPE_NO_ACCESS(15);
asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/);
// First clear all TT entries - ie Set them to Faulting
memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
//ARM_FIRST_LEVEL_PAGE_TABLE_SIZE = 0x4000 즉, ttb_base부터 0x4000만큼 0으로 clear
//X_ARM_MMU_SECTION 메크로 인자값
//(physical addr, virtual addr, size, cached, bufferd, access perm)
//다음은 phsycal - virtual의 연결이 이루어지는 코드이다.
X_ARM_MMU_SECTION(0x000, 0x800, 2, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // Flash
X_ARM_MMU_SECTION(0x300, 0x000, 64, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SDRAM
X_ARM_MMU_SECTION(0x400, 0x400, 1, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SRAM
X_ARM_MMU_SECTION(0x480, 0x480, 512, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // SFRs
X_ARM_MMU_SECTION(0x300, 0x300, 64, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW); // Raw SDRAM
}
... ... ... 생략 ... ... ...
댓글 없음:
댓글 쓰기