- KUSEG
- 사용자가 사용하는 공간
- TLB를 통해 physical addr로 변환
- KSEG0 (512M)
- cached (항상 cache를 사용함)
- cache 초기화 이후에 사용
- 상위 1bit (최상위 bit)를 0으로 만들어 physical addr로 변환
- TLB를 거치지 않고 access
- 커널이 이 영역을 사용
- KSEG1(512M)
- uncached (cache를 사용하지 않음)
- 시스템에서 cache가 정의되기 이전에 사용. (ex. reset vector addr = 0xBFC00000)
- 상위 3bit를 0으로 만들어 physical addr로 변환
- I/O 주변기기에 mapping (I/O 장치들은 그 특성상 cache를 사용해서는 안됨.)
- KSEG2(512M)
- 커널을 통해서 access 가능
- TLB를 통해 physical addr로 변환
2010년 1월 21일 목요일
MIPS memory map
Nand Flash Block 구조
2008년 7월 21일 월요일
bootloader porting with T32
BOX-X에 redboot을 포팅하는데 2주 걸렸다-_-) 이런, 수박바.
정말.. 끝내주는 삽질이었다-_-;
우선 T32를 이용한 cmm파일은 다음과 같다.
========================================================================================
B::
RESET
SYSTEM.OPTION waitreset.on
SYSTEM.CPU PXA255
SYSTEM.UP
Break.RESET
FLASH.RESET
FLASH.CREATE 0x00000000--0x3fffff 0x20000 I28F001J3 BYTE
FLASH.ERASE ALL
print "erase done"
FLASH.PROGRAM ALL
DATA.LOAD.binary Y:\x-station\u-boot-1.2.0-xstation\u-boot.bin 0x0 /word
FLASH.PROGRAM OFF
ENDDO
===========================================================================================
그리고 삽질끝에 알아낸 memory controller register value!!
보드는 CPU - PXA255에 flash - Inter strata flash 28F128이다.
D.S 0x48000000 %l 0x00000000 ;MDCNFG
D.S 0x48000004 %l 0x03CA4FFF ;MDREFR
D.S 0x48000008 %l 0x7FF07FF0 ;MSC0
D.S 0x4800000C %l 0x7FF07FF0 ;MSC1
D.S 0x48000010 %l 0x7FF07FF0 ;MSC2
D.S 0x48000014 %l 0x00000000 ;MECR
D.S 0x48000018 %l 0x00000000 ;SXLCR
D.S 0x4800001C %l 0x00040004 ;SXCNFG
D.S 0x48000020 %l 0x01FE01FE
D.S 0x48000024 %l 0x00000000 ;SXMRS
D.S 0x48000028 %l 0x00000000 ;MCMEM0
D.S 0x4800002C %l 0x00000000 ;MCMEM1
D.S 0x48000030 %l 0x00000000 ;MCATT0
D.S 0x48000034 %l 0x00000000 ;MCATT1
D.S 0x48000038 %l 0x00000000 ;MCIO0
D.S 0x4800003C %l 0x00000000 ;MCIO1
D.S 0x48000040 %l 0x00220022 ;MDMRS
D.S 0x48000044 %l 0x00000008 ;BOOT_DEF
D.S 0x48000058 %l 0x00000000 ;MDMRSLP
비록 cmm파일에 쓰이지 않았지만, 삽질의 결과다-_ㅠ) 흑흑..
2008년 7월 4일 금요일
redboot올릴 보드#2
IMO보드에 이어서 받은 보드는 타이눅스 BOX-X.
CPU: PXA255(Intel)
SDRAM: MT48LC8M16(Micron)
Flash: Strata E28F128(Intel)
아쉽게도 이 보드를 만든 팜팜테크가 현존하지 못해... 혼자 삽질해가야 겠다.ㅠ
bootloader라도 있어 다행이지만,
현재... flash날라간 상태.
2008년 4월 28일 월요일
REDBOOT (ver. smdk2410)
시스템이 시작되는 곳
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
}
2008년 1월 17일 목요일
시스템 초기화 루틴
시스템 초기화 루틴이란,
시스템에 power on 한 후 커널의 main 코드를 실행시키기 직전까지 수행시키는 일을 말한다. 즉, 커널에 주도권을 넘겨주기 전에 커널을 시스템상에 올리기 위하여 하는 일을 뜻한다.
power on 또는 reset시에 최초로 수행되는 부분이며, 메모리 0x0번지 부터 읽혀진다. 보통은 bank0의 flash memory에 위치한다.
초기화 루틴은 몇가지 단계를 거쳐 이루어지는데 다음과 같다.
Exception Vector Init → Disable Watch Dog Timer → Disable Interrupt → Clock Configuration → Memory Bank Init → Stack Init → Setup Exception Handler → Init Data Area → Jump to Main
즉, 초기화 단계는 Exception Vector를 설정하고 Exception Handler를 작성하고 메모리 시스템과 stack pointer를 초기화 하는 과정을 거치며 마지막에 C코드로 진입하게 된다.
2007년 11월 2일 금요일
bootloader란
장화의 끈을 묶고 일어서려는 사람이라는 설도 있고, 장화끈을 묶어주는 사람이라는 설도 있는데 아무튼 출발하기 직전의 준비작업이라는 의미가 되는 것 같다.
컴퓨터에서 bootloader는 OS의 최소부분을 메모리로 올려 프로세서가 이를 실행할 수 있게 해주는 일을 하는 녀석이다.
컴퓨터에 전원이 들어오면 시스템을 정상적으로 작동시킬 수 있도록 소프트웨어 및 하드웨어를 초기화 시키고 (■Memory setting, CPU clock setting ■GPIO setting, Serial setting ■MAC address, Ethernet port setting 등) 커널을 부팅시키는 일을 한다.
하드웨어에 dependent하게 짜여져 있기 때문에 어셈코드가 많으며 flash메모리에 저장되기 때문에 크기가 매우 작다.
bootloader의 종류는 매우 많은데 가장 많이 알려진 것들은 다음과 같다.