본문 바로가기

Architecture

망고64에 u-boot 포팅하기

/* 
이 자료는 
http://blog.naver.com/PostList.nhn?blogId=yhoh&categoryNo=19&currentPage=3
의 푸우 님의 자료를 거의 복사 하였으니 참고해 주시기 바랍니다.
*/



-boot Guide|작성자 bocholt














1. 삼성에서 공식적으로 배포한 u-boot-1.3.4-samsung_rel-1-0-4_20090305.tar.bz2을 이용합니다.

2. 망고64에 필요한 부분만 남기고 삭제합니다.

삭제한 내용
  - u-boot-1.3.4-feelpass/board 에서 samsung만 제외하고 삭제
  - u-boot-1.3.4-feelpass/board/samsung 에서 common과 smdk6410을 제외하고 삭제
  - u-boot-1.3.4-feelpass/cpu에서 s3c64xx를 제외하고 삭제
  - u-boot-1.3.4-feelpass/include 에서 

asm-avr32asm-blackfinasm-i386asm-m68kasm-microblaze,

asm-mipsasm-niosasm-nios2asm-ppcasm-shasm-sparc 파일 삭제

  - u-boot-1.3.4-feelpass 에서 

lib_avr32lib_blackfinlib_i386lib_m68klib_microblaze,

lib_mipslib_nioslib_nios2lib_ppclib_shlib_sparc 파일 삭제


  u-boot-1.3.4-feelpass/include/asm-arm에서 proc-armv와 arch-s3c64xx을 제외한 모든 부분을 삭제
  - u-boot-1.3.4-feelpass/config에서 smdk6410.h를 제외한 모든파일 삭제
  u-boot-1.3.4-feelpass 에서 필요없는 .mk 파일들을 삭제


  - make clean, make smdk6410_config, make 빌드 해본후 이상 없는지 확인합니다..

3. mango64 전용 폴더및 파일을 만듭니다..


yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass/board$ cp -a samsung/smdk6410/ mango64

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass/board$ ls

mango64  samsung

/board 에 mango64 폴더를 만들고 samsung/smdk6410 의 내용을 복사합니다..


yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass/board/mango64$ mv smdk6410.c mango64.c

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass/board/mango64$ mv smdk6410_val.h mango64_val.h

복사해온 mango64폴더에 smdk6410.c, smdk6410_val.h 을 각각 mango64.c, mango64_val.h로 변경합니다.

mango64_val.h (Z:\u-boot\uboot-1.3.4-pooh04\board\mango64)

#ifndef _VAL_MANGO64_H

#define _VAL_MANGO64_H

smdk6410_val.h를 mango64_val.h로 변경하겼기 때문에 mango64_val.h의 define 관련 부분 이름을 바꾸어 준다. _VAL_SMDK6410_H 를 _VAL_MANGO64_H로 변경

mango64.c로 변경했기 때문에 Makefile의 내용도 바꾸어 줍니다..


Makefile (Z:\u-boot\uboot-1.3.4-pooh04\board\mango64)

OBJS              := mango64.o flash.o

SOBJS              := lowlevel_init.o

mango64.c 로 변경했기 때문에 그에 맞도록 Makefile의 내용도 바꾸어 줍니다.


u-boot.lds (Z:\u-boot\uboot-1.3.4-pooh04\board\mango64)

.text      :

        {

          cpu/s3c64xx/start.o   (.text)

          cpu/s3c64xx/start_irom.o      (.text)

          cpu/s3c64xx/s3c6410/cpu_init.o        (.text)

          board/mango64/lowlevel_init.o (.text)

          cpu/s3c64xx/onenand_cp.o      (.text)

          cpu/s3c64xx/nand_cp.o (.text)

          cpu/s3c64xx/movi.o (.text)

          *(.text)

          lib_arm/div0.o

        }

 복사해온 mango64 폴더에는 u-boot.lds 파일이 들어있다.. 이것은 scatter loader 파일입니다. 원래는 board/samsung/smdk6410/lowlevel_init.o로 되어 있는 것을 board/mango64/lowlevel_init.o로 수정

lowlevel_init.S (Z:\u-boot\uboot-1.3.4-pooh04\board\mango64)

#include "mango64_val.h"

복사해온 mango64 폴더에서 lowlevel_init.S도 변경이 필요하다. 원래 #include "smdk6410_val.h" 고 되어 있던 부분을 "mango64_val.h"로 변경.

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass/include/configs$ cp smdk6410.h mango64.h

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass/include/configs$ ls

mango64.h  smdk6410.h

include/configs에 들어있는 smdk6410.h를 mango64.h로 복사.

/* samsung socs: auto-detect devices */

#if defined(CONFIG_SMDK6410) || defined(CONFIG_SMDK6430) || defined(CONFIG_SMDKC100) || defined(CONFIG_MANGO64)

위 내용은 board.c(/lib_arm)의 404라인 내용이다. CONFIG_MANGO64관련 define을 추가해 준다. 물론 아직 CONFIG_MANGO64는 정의되어 있지 않다. 원래 CONFIG_SMDK6410이 smdk6410.h에 #define CONFIG_SMDK6410 1로 정의되어 있는데 이것을 mango64.h로 복사 했기 때문에 이 파일에서 위 정의를 추가해 주어야 합니다.

mango64.h (Z:\u-boot\uboot-1.3.4-feelpass\include\configs)

#define CONFIG_MANGO64                            1                            /* on a MANGO64 Board  */

위와 같이 mango64.h에 변경해 놓습니다..


hs_mmc.c (Z:\u-boot\uboot-1.3.4-feelpass\cpu\s3c64xx)

#if defined(CONFIG_SMDK6400) || defined(CONFIG_SMDK6410) || defined(CONFIG_SMDK6430) || defined(CONFIG_MANGO64)

 

hs_mmc.c 라인 번호 3 부분에도 CONFIG_MANGO64 정의를 포함해 놓습니다.

 

Makefile (Z:\u-boot\uboot-1.3.4-feelpass)

mango64_config              :              unconfig

              @$(MKCONFIG) $(@:_config=) arm s3c64xx mango64 NULL s3c6410

 

가장 상위 폴더에 존재하는 Makefile에 위의 내용을 포함시킵니다. 이것은 smdk6410_config를 복사해서 적절히 수정한 것에 지나지 않음.



smdk6410_config              :              unconfig

              @$(MKCONFIG) $(@:_config=) arm s3c64xx smdk6410 samsung s3c6410

 

위 내용이 원래 들어있는 smdk6410_config 내용이다. 이 내용은 삭제된 것이 아니라 그대로 내용에 포함되어 있습니다. 다만 한가지 다른 부분이 있는데 MKCONFIG에 전달되는 파라미터 중에서 smdk6410으로 보드 이름이 적히던 부분이 mango64로 변해 있고, 바로 다음의 samsung이라고 되어 있는 부분이 NULL로 변화되어 있습니다.

 

board/samsung/smdk6410을 복사해서 board/mango64로 만들었는데 여기서 samsung이라는 이름이 바로 Vendor 이름입니다. 만약 Vendor 이름이 있을 경우는 위의 경우처럼 board 폴더에 바로 그 Vendor 이름이 폴더로 존재하게 됩니다. mango64는 board 폴더의 바로 밑에 있기 때문에 이 Vendor 이름이 NULL로 존재해야 합니다.

 

MKCONFIG              := $(SRCTREE)/mkconfig

 

MKCONFIG는 위와 같이 mkconfig로 정의되어 있고 mkconfig를 찾아보면 아래의 내용을 발견할 수 있습니다.

 

mkconfig (Z:\u-boot\uboot-1.3.4-feelpass)

echo "ARCH   = $2" >  config.mk

echo "CPU    = $3" >> config.mk

echo "BOARD  = $4" >> config.mk

[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk

 

config.mk (Z:\u-boot\uboot-1.3.4-feelpass)

ifdef              VENDOR

BOARDDIR = $(VENDOR)/$(BOARD)

else

BOARDDIR = $(BOARD)

endif

 

결국 Vendor에 대한 정의를 하는지 그렇지 않은지에 따라서 Board Directory 이름이 변경되고 있음을 알수 있습니다. 우리는 Vendor를 Null로 해서 이름을 만들지 않으려고 하는 것입니다..


Makefile (Z:\u-boot\uboot-1.3.4-feelpass\drivers\mtd\onenand)

ifeq ($(BOARD),smdk6400)

COBJS += s3c_onenand.o

else ifeq ($(BOARD),smdk6410)

COBJS += s3c_onenand.o

else ifeq ($(BOARD),mango64)

COBJS += s3c_onenand.o

else ifeq ($(BOARD),smdk6430)

COBJS += s3c_onenand.o

else ifeq ($(BOARD),smdkc100)

COBJS += s3c_onenand.o

else

COBJS += onenand_base.o onenand_bbt.o

endif

 

위와 같이 mango64와 관련해서도 추가를 해주어야 합니다. 실제로는 One NAND를 사용하지 않기 때문에 필요 없는 부분이기는 하지만 대부분에 대해서 smdk6410 것을 아직은 그저 복사한 수준이기 때문에 이 부분이 포함되지 않으면 컴파일 시에 에러가 발생하게 됩니다.


mango64.c (Z:\u-boot\uboot-1.3.4-feelpass\board\mango64)

int checkboard(void)

{

              printf("Board:   MANGO64\n");

              return (0);

}

 

mango64.h (Z:\u-boot\uboot-1.3.4-feelpass\include\configs)

#define CFG_PROMPT                            "MANGO64 # "              /* Monitor Command Prompt              */

 

#define CONFIG_IDENT_STRING              " for MANGO64"

 

위에서 변한 부분은 단순히 출력에 대한 부분을 Mango64로 변경한 것입니다.

 

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass$ make mango64_config

Configuring for mango64 board...

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass$ make

Generating include/autoconf.mk.dep

..... ..... ..... ..... ..... .....

/home/yhoh/wk/poohdroid/prebuilt/linux-x86/toolchain/arm-eabi-4.3.1/bin/arm-eabi-objcopy --gap-fill=0xff -O binary u-boot

u-boot.bin

yhoh@CRZ-PC1:~/u-boot/uboot-1.3.4-feelpass$

 



uboot-1.3.4-pooh05\include\configs\mango64.h

//#define CONFIG_ENABLE_MMU

#ifdef CONFIG_ENABLE_MMU

#define virt_to_phys(x)              virt_to_phy_smdk6410(x)

#else

#define virt_to_phys(x)              (x)

#endif

 

일단 U-Boot 상에서는 MMU를 사용하지 않도록 설정합니다.

MMU를 사용하지 않기 때문에 Virtual Address를 Physical Address로 변환할 때

특별한 작업을 수행할 필요가 없게 됩니다.

 

\cpu\s3c64xx\Makefile

ifeq ($(BOARD),smdk6400)

START              += start_6400.o

else ifeq ($(BOARD),mango64)

START              += start_6400.o

else

START              += start_irom.o

endif

 

현재는 IROM booting을 사용하고 있지 않기 때문에 start_6400.S를 이용하게 됩니다.

 




uboot-1.3.4-pooh05/cpu/s3c64xx를 살펴보면 위 내용을 발견할 수 있습니다.

이들 파일들이 보드의 초기 수행 시점에서 매우 중요한 역할을 하는 부분들입니다.

 

uboot-1.3.4-pooh05\board\mango64\config.mk

ifndef TEXT_BASE

TEXT_BASE = 0x57e00000

endif

 

기존에 사용하던 u-boot binary에서 Text 주소값으로 매우 익숙한 값이 이곳에 설정되고 있습니다.

이 값이 원래는 TEXT_BASE = 0xc7e00000로 되어 있었습니다.

이 주소는 맞지 않기 때문에 0x57e00000으로 변경합니다.

 

uboot-1.3.4-pooh05\board\mango64\u-boot.lds

              .text      :

              {

                cpu/s3c64xx/start.o              (.text)

                cpu/s3c64xx/start_6400.o              (.text)

                cpu/s3c64xx/s3c6410/cpu_init.o              (.text)

                board/mango64/lowlevel_init.o              (.text)

                cpu/s3c64xx/onenand_cp.o              (.text)

                cpu/s3c64xx/nand_cp.o              (.text)

                cpu/s3c64xx/movi.o (.text)

                *(.text)

                lib_arm/div0.o

              }

 

u-boot.lds Scatter Loader 부분을 또 변경해 주어야 하는 부분이 있습니다.

원래 cpu/s3c64xx/start_irom.o (.text)로 되어 있는 부분을

cpu/s3c64xx/start_6400.o (.text)로 변경해야 합니다.

 

uboot-1.3.4-pooh05\cpu\s3c64xx\start.S

#if !defined(CONFIG_S3C6400) && !defined(CONFIG_MANGO64)

              moveq              r3, #0xf                            /* r0 == r1 then skip flash copy   */

              bl              load_bl2_irom

#else

              beq              after_copy

              bl              load_bl2_6400

#endif

 

load_bl2_irom 대신에 load_bl2_6400가 실행될 수 있도록

!defined(CONFIG_MANGO64)를 start.S에 추가합니다.


일단 현재까지의 상태에서 빌드를 해서 다운로드를 해보았습니다.




다운로드는 문제없이 동작하였고, Checksum까지 통과했는데

아무 것도 출력이 이루어지지 않고 있습니다.

뭔가 Serial 쪽에 변경이 필요한 것이 아닐까 하는 생각을 해봅니다.



디버그 포트로 사용하는 부분의 회로도를 잠시 보도록 하겠습니다.





위와 같이 UART1_TXD를 사용하고 있는 것을 알수 있고,






UART1_xxx가 GPA4, 5, 6, 7에 할당된 것을 알수 있습니다.




UART1_xxx는 XuXXX[1] 부분임을 알수 있습니다.









GPA4, 5, 6, 7이 UART1을 가리키는 부분입니다.

 

여기서 실제 소스 부분을 살펴보도록 하겠습니다.

 

s3c6410.h (include)

#ifdef CONFIG_SERIAL1

#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)

#elif defined(CONFIG_SERIAL2)

#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET)

#elif defined(CONFIG_SERIAL3)

#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET)

#elif defined(CONFIG_SERIAL4)

#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART3_OFFSET)

#else

#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)

#endif

 

위와 같이 s3c6410.h 부분을 보면 UART0는 CONFIG_SERIAL1이고,

UART1은 CONFIG_SERIAL2 임을 알수 있습니다.

 

mango64.h (include\configs)

#define CONFIG_SERIAL2          1 /* mango64 use UART1 (SERIAL 2) */

 

망고 64는 UART1을 사용하기 때문에 CONFIG_SERIAL2를 define해주어야 합니다.

위와 같이 CONFIG_SERIAL2를 1로 설정해주도록 변경했습니다.

 

Checksum O.K.

H?

 

U-Boot 1.3.4 (Jan 15 2010 - 12:12:17) for MANGO64

CPU:     S3C6410@532MHz

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)

Board:   MANGO64

DRAM:    128 MB

Flash:   0 kB

SD/MMC:  0 MB

NAND:    0 MB

 

이제 다시 빌드해서 다운로드 후 실행해 보면 위와 같이 출력이 나오고 있습니다.

그렇지만 아직도 정상적으로 작동하고 있지는 않습니다.

 

릴리즈 된 Mango64-u-boot-1.1.6-V01-000.bin을 사용해서 출력되는 것과 비교해 보도록 합니다.

 

Checksum O.K.

H?

 

U-Boot 1.1.6 (Nov 11 2009 - 23:12:28) for SMDK6410

CPU:     S3C6410@532MHz

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)

Board:   SMDK6410

DRAM:    128 MB

Flash:   0 kB

NAND:    256 MB

*** Warning - bad CRC or NAND, using default environment

In:      serial

Out:     serial

Err:     serial

Hit any key to stop autoboot:  0

mango6410 #

 

이렇게 비교를 하면 힘드니까 강제적으로 비교 툴을 사용해 보겠습니다.

 







버전이나 출력되는 것이 다른 것을 제외하면 NAND 부분이 좀 다르네요.

클럭은 동일하게 설정되어 있는 것으로 보입니다.

 






다음 변경된 사항은 아래와 같습니다.

 

uboot-1.3.4-pooh07\common\Makefile

ifeq ($(CPU),s3c24xx)

COBJS += env_nand.o env_movi.o env_onenand.o

else ifeq ($(BOARD),mango64)

COBJS += env_nand.o

else

ifeq ($(BOARD),smdk6400)

COBJS += env_nand.o env_movi.o env_onenand.o

else

COBJS += env_auto.o

endif

endif

 

common의 Makefile을 위와 같이 수정했습니다.

일단 One NAND나 Movi NAND의 경우는 제외하고

mango64에서는 env_nand만 포함되도록 추가하였습니다.

 

lowlevel_init.S (board\mango64)

lowlevel_init:

..... ..... ..... ..... ..... .....

              /* for UART */

              bl uart_asm_init

#if defined(CONFIG_NAND) /* Nand Initialization */

              /* simple init for NAND */

              bl nand_asm_init

#endif

 

board\mango64의 lowlevel_init.S에서 lowlevel_init에서 진행하는 과정 중에

uart_asm_init 바로 다음에 NAND를 초기화 해주는 부분을 삽입합니다.

nand_asm_init을 호출하고 있습니다.

 

uboot-1.3.4-pooh07\include\configs\mango64.h

..... ..... ..... ..... ..... .....

#define CFG_ONENAND_BASE               (0x70100000)

#define CFG_MAX_ONENAND_DEVICE              1

#define CONFIG_BOOT_NAND

#define CONFIG_NAND

#define CFG_ENV_IS_IN_NAND

//#define CFG_ENV_IS_IN_AUTO

#endif              /* __CONFIG_H */

 

우리는 향후 U-Boot를 NAND에 저장한 이후에 NAND에서 부팅을 할 수 있도록 만들 것입니다.

위에서 살펴본 config를 이곳에서 정의하고 있는 것입니다.

CONFIG_BOOT_NANDCONFIG_NANDCFG_ENV_IS_IN_NAND를 각각 정의합니다.

ENV 관련한 사항은 환경 변수들로서 이것 또한 NAND에 저장할 것입니다.

원래 정의되어 있던 CFG_ENV_IS_IN_AUTO 부분은 삭제합니다.

자동으로 저장될 곳을 찾아서 저장하는 것인데 우리는 NAND에 저장할 것이기 때문에

기본적으로 CFG_ENV_IS_IN_NAND를 정의하고 AUTO는 삭제합니다.

 

이렇게 변경된 내용을 빌드해서 보드에서 수행시켜 보도록 하겠습니다.

 

U-Boot 1.3.4 (Jan 18 2010 - 15:22:49) for MANGO64

CPU:     S3C6410@532MHz

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)

Board:   MANGO64

DRAM:    128 MB

Flash:   0 kB

SD/MMC:  0 MB

NAND:    256 MB

 

s3c-nand: ECC uncorrectable error detected

s3c-nand: 1 bit error detected at byte 194, correcting from 0xcd to 0x8d...OK

s3c-nand: 1 bit error detected at byte 507, correcting from 0xe5 to 0xe1...OK

..... ..... ..... ..... ..... .....

s3c-nand: ECC uncorrectable error detected

s3c-nand: 1 bit error detected at byte 123, correcting from 0x0a to 0x8a...OK

 

*** Warning - bad CRC or NAND, using default environment

*** Error - default environment is too large

In:      serial

Out:     serial

Err:     serial

Net:     No ethernet found

 

MANGO64 #

 

드디어 MANGO64 # 프롬프트가 보입니다. ^)^

이제 여러가지 명령들을 수행할 수 있는 단계가 된 것입니다.

 

초기에 출력하고 있는 메세지들을 살펴보면

NAND:    256 MB

이전까지는 출력하지 못하던 NAND 크기가 출력되고 있습니다.

 

이후에 ECC 관련해서 매우 긴 내용이 출력되었습니다.

 

*** Error - default environment is too large

Net:     No ethernet found

 

위 2개의 문장이 처리되어야 할 부분으로 보입니다.

환경 변수들에 대한 저장 부분을 위치나 크기 등의 사항에 대해 변경이 필요해 보이고

Ethernet과 관련해서도 적절한 설정이 필요해 보입니다.






 환경 변수의 크기와 관련한 부분만 수정해 보겠습니다.

 

*** Error - default environment is too large

 

uboot-1.3.4-pooh07에서 위의 에러 메세지가 출력되었습니다.

이 부분을 찾아보면 아래 부분입니다.

 

void set_default_env(void)

{

    if (sizeof(default_environment) > ENV_SIZE) {

        puts ("*** Error - default environment is too large\n\n");

        printf("sizeof(default_environment): %d\n", sizeof(default_environment));

        printf("CFG_ENV_SIZE: %d, ENV_SIZE: %d\n", CFG_ENV_SIZE, ENV_SIZE);

        return;

    }

..... ..... ..... ..... ..... .....

 

위와 같이 2개의 printf를 추가해서 실제 에러가 발생한 크기를 측정해 보았습니다.

 

sizeof(default_environment): 16384

CFG_ENV_SIZE: 16384, ENV_SIZE: 16380

 

ENV_SIZE environment.h (include)에 아래와 같이 정의되어 있습니다.

 

#ifdef CFG_REDUNDAND_ENVIRONMENT

# define ENV_HEADER_SIZE              (sizeof(uint32_t) + 1)

#else

# define ENV_HEADER_SIZE              (sizeof(uint32_t))

#endif

#define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE)

 

ENV_HEADER_SIZE는 CFG_REDUNDAND_ENVIRONMENT가 정의되어 있지 않기 때문에

sizeof(uint32_t)로 정의될 것이고, 4 값을 가질 것입니다.

CFG_ENV_SIZE에서 4를 뺀 값을 ENV_SIZE로 갖고 있을 것입니다.

 

env_common.c (common)

#if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430) || defined(CONFIG_S5PC100)

uchar default_environment[CFG_ENV_SIZE] = {

#else

uchar default_environment[] = {

#endif

 

default_environment가 CFG_ENV_SIZE 크기의 배열로 잡혀 있기 때문에

이것의 크기를 sizeof 연산을 하게 되면 16384가 됩니다.

결국 늘 크기가 맞지 않을 수 밖에 없는 것입니다.

 

위 코드를 아래와 같이 수정하도록 하겠습니다.

 

#if defined(CONFIG_MANGO64)

uchar default_environment[] = {

#elif defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430) || defined(CONFIG_S5PC100)

uchar default_environment[CFG_ENV_SIZE] = {

#else

uchar default_environment[] = {

#endif

 

크기를 지정하지 않고 일단 현재 정의된 것의 크기만 가질 수 있도록 변경했습니다.

 

sizeof(default_environment): 171

 

변경 후에 수행시켜보면

현재의 default_environment에 저장되는 것은 고작 171 바이트 밖에는 안되네요.

 

uboot-1.3.4-pooh09

 

board.c (lib_arm)

void start_armboot (void)

{

..... ..... ..... ..... ..... .....

/* samsung socs: auto-detect devices */

#if defined(CONFIG_SMDK6410) || defined(CONFIG_SMDK6430) || defined(CONFIG_SMDKC100)

..... ..... ..... ..... ..... .....

/* samsung socs: no auto-detect devices */

#elif defined(CONFIG_SMDK6400) || defined(CONFIG_SMDK2450) || defined(CONFIG_SMDK2416) || defined(CONFIG_MANGO64)

..... ..... ..... ..... ..... .....

 

lib_arm의 board.c를 보면 start_armboot() 함수가 있고

여기에서 두 부분으로 나누어서 초기화를 진행하고 있습니다.

우리는 auto-detect로 동작하도록 하는 것이 아니기 때문에

기존에 CONFIG_SMDK6410 부분에 OR로 포함시켰던 CONFIG_MANGO64

no auto-detect 부분으로 설정을 변경하였습니다.



이제 Ethernet 부분을 설정하도록 하겠습니다.




망고 64 회로도를 보면 Ethernet이 EBI CSN4로 설정되어 있는 것을 알수 있습니다.

 

/* mango64 use SROM bank 4 for Ethernet */

#define CS8900_SROM_BANK_4

 

static void cs8900_pre_init(void)

{

#if defined(CS8900_SROM_BANK_1)

              SROM_BW_REG &= ~(0xf << 4);

              SROM_BW_REG |= (1<<7) | (1<<6) | (1<<4);

              SROM_BC1_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));

#elif defined(CS8900_SROM_BANK_2)

              SROM_BW_REG &= ~(0xf << 8);

              SROM_BW_REG |= (1<<11) | (1<<10) | (1<<8);

              SROM_BC2_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));

#elif defined(CS8900_SROM_BANK_3)

              SROM_BW_REG &= ~(0xf << 12);

              SROM_BW_REG |= (1<<15) | (1<<14) | (1<<12);

              SROM_BC3_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));

#elif defined(CS8900_SROM_BANK_4)

              SROM_BW_REG &= ~(0xf << 16);

              SROM_BW_REG |= (1<<19) | (1<<18) | (1<<16);

              SROM_BC4_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));

#elif defined(CS8900_SROM_BANK_5)

              SROM_BW_REG &= ~(0xf << 20);

              SROM_BW_REG |= (1<<23) | (1<<22) | (1<<20);

              SROM_BC5_REG = ((CS8900_Tacs<<28)+(CS8900_Tcos<<24)+(CS8900_Tacc<<16)+(CS8900_Tcoh<<12)+(CS8900_Tah<<8)+(CS8900_Tacp<<4)+(CS8900_PMC));

#endif

}

 

cs8900_pre_init() 부분에서 이것을 설정하는 부분을 찾을 수 있습니다.

두 개의 레지스터를 설정해야 합니다.

SROM_BW_REG SROM BUS WIDTH & WAIT CONTRL REGISTER(SROM_BW)이고

SROM_BCx_REG는 SROM bank 0부터 5까지의 6개에 대해서 각각 다른 레지스터 입니다.

 

현재 망고 64에는 SMSC LAN9220이 탑재되어 있습니다.

SMDK6410에는 CS8900이 탑재되어 있습니다.

함수 이름이 cs8900_으로 시작하는 것은 이것을 기반으로 했기 때문입니다.

 

mango64.h (include\configs)

//#define CONFIG_NET_MULTI // MANGO64

 

만약 CONFIG_NET_MULTI가 정의되어 있을 경우에는

CS8900과 SMSC LAN9220을 동시에 사용하게 됩니다.

망고 64는 SMSC LAN9220 만을 사용하기 때문에 CONFIG_NET_MULTI는 정의하지 않습니다.

 

#define CONFIG_DRIVER_SMC911X     1 // MANGO64

 

위와 같이 CONFIG_DRIVER_SMC911X를 1로 정의하고 있습니다.

실제로 망고64에서 사용하는 것은 SMC9220이지만

대부분의 코드가 911X로 정의된 값을 이용하고 있습니다.

 

#define CONFIG_DRIVER_SMC911X_BASE              0x30000000 // Mango64

 

기존 코드에서는 #define CONFIG_DRIVER_SMC911X_BASE 0x18800300으로 정의되어 있는데

이 부분은 SROM Bank 1을 사용하던 것입니다.

망고64에서는 SROM Bank 4를 사용하기 때문에

base 주소는 0x3000000 번지 입니다.

기존 코드에서 300으로 base 주소가 되어 있는데

이것은 CS8900의 잔재로서 LAN9220에서는 필요가 없습니다.



이제 uboot-1.3.4-pooh09를 빌드해서 수행해 보도록 합니다.

 

MANGO64 # setenv ipaddr 192.168.11.110

MANGO64 # setenv serverip 192.168.11.120

MANGO64 # setenv gatewayip 192.168.11.1

MANGO64 # ping 192.168.11.120

smc911x: initializing

smc911x: detected LAN9220 controller

smc911x: phy initialized

smc911x: MAC 00:40:5c:26:0a:5b

host 192.168.11.120 is alive

MANGO64 #

 

위와 같이 IP 설정을 수행하고 정상적으로 ping도 수행되는 것을 확인할 수 있었습니다.

 

MANGO64 # save

Saving Environment to NAND...

Erasing Nand...

Skipping bad block at  0x0007c000                                           

Writing to Nand... amount_saved: 0

FAILED!

MANGO64 #

 

save를 수행해 보았는데 뭔가 문제가 있습니다.

이 부분은 다음 시간에 하도록 하겠습니다.




달라진 부분은 오직 mango64.h뿐입니다.

 

#define CONFIG_BOOTARGS                  "rootfstype=jffs2 root=/dev/mtdblock2 init=/init console=ttySAC1,115200"

#define CONFIG_ETHADDR              00:40:5c:26:0a:5b

#define CONFIG_NETMASK      255.255.255.0

#define CONFIG_IPADDR                            192.168.11.110

#define CONFIG_SERVERIP              192.168.11.120

#define CONFIG_GATEWAYIP              192.168.11.1

 

나중을 대비해서 각종 설정 부분을 제가 사용하는 것으로 변경했습니다.

CONFIG_BOOTARGSCONFIG_IPADDRCONFIG_SERVERIPCONFIG_GATEWAYIP를 변경합니다.

 

/* 0x40000 - 0x4000 = 0x3C000 */

#define CFG_ENV_OFFSET                            0x0003C000

#define CFG_NAND_LARGEPAGE_SAVEENV

 

NAND의 영역은 아래의 그림과 같이 나뉠 예정입니다.






환경 데이타의 크기는 CFG_ENV_SIZE에서 0x4000으로 정의되어 있습니다.

이 부분을 U-Boot 영역으로 잡아놓은 공간의 가장 뒷 부분에 저장할 것입니다.

이를 위해서 환경 변수가 저장될 위치를 0x3C000으로 설정해야 합니다.

이 경우 16 kbytes의 공간을 저장하는 것이기 때문에

CFG_NAND_LARGEPAGE_SAVEENV를 설정해서

여러 page에 걸쳐서 저장이 일어날 수 있도록 설정해야 합니다.

우리가 사용하는 NAND의 경우 하나의 페이지 크기는 2kbytes 입니다.

 

//#define CONFIG_MMC // MANGO64

#define CONFIG_MTDPARTITION              "40000 400000 4000000"

 

MMC의 경우는 U-boot에서는 현재 사용하지 않기 때문에 막아 두었습니다.

CONFIG_MTDPARTITION은 위 그림에서와 같이 주소를 할당해 두었습니다.

 

#define CONFIG_BOOTCOMMAND              "nand read 50008000 40000 200000;bootm 50008000"

 

나중에 U-boot가 Kernel을 로딩할때 위의 방법으로 할수 있도록 미리 설정을 해두었습니다.

 

이제 빌드를 해서 실행해 보도록 하겠습니다.

 

MANGO64 # print

bootargs=rootfstype=jffs2 root=/dev/mtdblock2 init=/init console=ttySAC1,115200

bootcmd=nand read 50008000 40000 200000;bootm 50008000

mtdpart=40000 400000 4000000

bootdelay=3

baudrate=115200

ethaddr=00:40:5c:26:0a:5b

ipaddr=192.168.11.110

serverip=192.168.11.120

gatewayip=192.168.11.1

netmask=255.255.255.0

stdin=serial

stdout=serial

stderr=serial

Environment size: 350/16380 bytes

MANGO64 #

 

print를 해보면 우리가 설정한 모든 것들이 정상적으로 출력되는 것을 확인할 수 있습니다.

 

MANGO64 # tftp 51000000 u-boot.bin

smc911x: initializing

smc911x: detected LAN9220 controller

smc911x: phy initialized

smc911x: MAC 00:40:5c:26:0a:5b

TFTP from server 192.168.11.120; our IP address is 192.168.11.110

Filename 'u-boot.bin'.

Load address: 0x51000000

Loading: ###############

done

Bytes transferred = 219624 (0x359e8)

 

이제 NAND에 실제로 U-boot 바이너리를 저장하기 위해서 메모리에 다운로드를 받았습니다.

tftp를 통해서 PC로부터 u-boot.bin을 정확하게 다운받고 있습니다.

 

MANGO64 # nand erase 0 40000

NAND erase: device 0 offset 0x0, size 0x40000

Erasing at 0x20000 -- 100% complete.

OK

 

메모리에 다운 받은 u-boot.bin을 NAND에 저장하기 위해서

0 ~ 40000 부분의 NAND를 먼저 erase 하고 있습니다.

 

MANGO64 # nand write 51000000 0 40000

NAND write: device 0 offset 0x0, size 0x40000

262144 bytes written: OK

 

erase한 영역에 메모리의 데이타를 Write하고 있습니다.

 

MANGO64 # save

Saving Environment to NAND...

Erasing Nand...

Erasing at 0x20000 -- 100% complete.

Writing to Nand... done

 

환경 변수를 저장하고 있습니다.

 

이제 NAND로 부팅 모드를 변경해서 부팅을 해보도록 하겠습니다.

 

U-Boot 1.3.4 (Jan 18 2010 - 21:52:25) for MANGO64

CPU:     S3C6410@532MHz

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC

Mode)

Board:   MANGO64

DRAM:    128 MB

Flash:   0 kB

NAND:    256 MB

In:      serial

Out:     serial

Err:     serial

Hit any key to stop autoboot:  0

MANGO64 #

 

NAND로도 정확하게 부팅이 되는 것을 확인할 수 있었습니다.

 

이제 기존에 우리가 가지고 있던 망고 64용 커널과 파일 시스템을 올려보도록 하겠습니다.

 

MANGO64 # setenv ipaddr 192.168.11.110; setenv serverip 192.168.11.120; sete

nv gatewayip 192.168.11.1; setenv bootcmd "nand read 50008000 40000 200000;b

ootm 50008000"; setenv bootargs rootfstype=jffs2 root=/dev/mtdblock2 init=/i

nit console=ttySAC1,115200

MANGO64 # tftp 51000000 Mango64-kernel-2.6.29-V01-000.zImage; nand erase 400

00 200000; nand write 51000000 40000 200000;

smc911x: initializing

smc911x: detected LAN9220 controller

smc911x: phy initialized

smc911x: MAC 00:40:5c:26:0a:5b

TFTP from server 192.168.11.120; our IP address is 192.168.11.110

Filename 'Mango64-kernel-2.6.29-V01-000.zImage'.

Load address: 0x51000000

Loading: #################################################################

             ################################################################

done

Bytes transferred = 1880204 (0x1cb08c)

NAND erase: device 0 offset 0x40000, size 0x200000

Skipping bad block at  0x00040000

Skipping bad block at  0x00060000

Skipping bad block at  0x00080000

Skipping bad block at  0x000a0000

Erasing at 0x220000 -- 100% complete.

OK

NAND write: device 0 offset 0x40000, size 0x200000

2097152 bytes written: OK

 

커널을 다운로드 하는 것은 문제없이 동작한 것으로 보입니다.

 

MANGO64 # tftp 0x51000000 Mango64-AndroidCupcake-V01-000.jffs2; nand erase 0

x400000 0x4000000; nand write.jffs2 0x51000000 0x400000 0x1da0000; save; sav

e; re

smc911x: initializing

smc911x: detected LAN9220 controller

smc911x: phy initialized

smc911x: MAC 00:40:5c:26:0a:5b

TFTP from server 192.168.11.120; our IP address is 192.168.11.110

Filename 'Mango64-AndroidCupcake-V01-000.jffs2'.

Load address: 0x51000000

Loading: #################################################################

..... ..... ..... ..... ..... .....

              #####################################

done

Bytes transferred = 31064064 (0x1da0000)

NAND erase: device 0 offset 0x400000, size 0x4000000

Skipping bad block at  0x02600000                                          

Erasing at 0x43e0000 -- 100% complete.

OK

NAND write: device 0 offset 0x400000, size 0x1da0000

Writing data at 0x219f800 -- 100% complete.

31064064 bytes written: OK

Saving Environment to NAND...

Erasing Nand...

Erasing at 0x20000 -- 100% complete.

Writing to Nand... done

Saving Environment to NAND...

Erasing Nand...

Erasing at 0x20000 -- 100% complete.

Writing to Nand... done

reset...

 

파일 시스템 역시 정상적으로 저장이 된 것으로 보입니다.

 

U-Boot 1.3.4 (Jan 18 2010 - 21:52:25) for MANGO64

CPU:     S3C6410@532MHz

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC

Mode)

Board:   MANGO64

DRAM:    128 MB

Flash:   0 kB

NAND:    256 MB

In:      serial

Out:     serial

Err:     serial

Hit any key to stop autoboot:  0

NAND read: device 0 offset 0x40000, size 0x200000

s3c-nand: ECC uncorrectable error detected

s3c-nand: 1 bit error detected at byte 205, correcting from 0x00 to 0x80...OK

s3c-nand: 1 bit error detected at byte 219, correcting from 0x00 to 0x20...OK

s3c-nand: ECC uncorrectable error detected

s3c-nand: ECC uncorrectable error detected

..... ..... ..... ..... ..... .....

s3c-nand: 1 bit error detected at byte 499, correcting from 0x00 to 0x08...OK

s3c-nand: 1 bit error detected at byte 23, correcting from 0x00 to 0x01...OK

s3c-nand: 1 bit error detected at byte 298, correcting from 0x00 to 0x02...OK

s3c-nand: ECC uncorrectable error detected

2097152 bytes read: ERROR

get_format

-------- 0 --------

Wrong Image Format for bootm command

ERROR: can't get kernel image!

MANGO64 #

 

뭔가 ECC 관련해서 좀더 확인이 필요해 보입니다.








uboot-1.3.4-pooh10에서 문제가 되었던 부분이 ECC 관련한 것이었습니다.

불현듯 떠오르는 생각이 왠지 nand scrub을 수행하지 않았기 때문이 아닐까 합니다.

 

MANGO64 # nand scrub

NAND scrub: device 0 whole chip

Warning: scrub option will erase all factory set bad blocks!

         There is no reliable way to recover them.

         Use this command only for testing purposes if you

         are sure of what you are doing!

Really scrub this NAND flash? <y/N>

Erasing at 0x23c0000 --  14% complete.

NAND 256MiB 3,3V 8-bit: MTD Erase failure: -5

Erasing at 0xeb80000 --  92% complete.

NAND 256MiB 3,3V 8-bit: MTD Erase failure: -5

Erasing at 0xffe0000 -- 100% complete.

Scanning device for bad blocks

s3c-nand: ECC uncorrectable error detected

s3c-nand: ECC uncorrectable error detected

s3c-nand: ECC uncorrectable error detected

s3c-nand: ECC uncorrectable error detected

OK

 

위와 같이 nand scrub을 수행한 이후에 커널과 파일 시스템을 다운로드 했을 때

정상적으로 안드로이드 화면까지 부팅하는 것을 확인했습니다.

 

uboot-1.3.4-pooh11

 

mango64.h (include\configs)

#define CFG_NAND_HWECC

#define CONFIG_NAND_BL1_8BIT_ECC

 

mango64.h에 보면 위와 같이 정의되어 있는 것을 발견할수 있습니다.

Hardware ECC를 사용하고 있는 것이고, 8 비트 ECC를 사용하도록 설정되어 있습니다.

 

6410 매뉴얼을 살펴보면 아래와 같이 기술되어 있습니다.

 

Support both SLC and MLC NAND flash memory : 1-bit ECC, 4-bit and 8-bit ECC for NAND flash.

(Recommend: 1bit ECC for SLC, 4bit and 8bit ECC for MLC NAND Flash)

 

망고 64에서 사용하는 NAND인 K9F2G08U0M는 SLC NAND 입니다.

그러므로 1-bit ECC를 사용해야 하고

위에서 CONFIG_NAND_BL1_8BIT_ECC는 삭제하는 것이 맞을 것으로 판단됩니다.

 

//#define CONFIG_NAND_BL1_8BIT_ECC

 

위와 같이 코드 상에서 주석으로 처리하였습니다.

uboot-1.3.4-pooh11에서 주요하게 달라진 것은 위의 코드입니다.

 

#define CONFIG_BOOTCOMMAND              "nand read 50008000 40000 400000;bootm 50008000"

 

추가적으로 향후 커널이 증가할 것을 대비해서 위와 같이

NAND에서 읽어오는 부분을 200000에서 400000으로 변경하였습니다.

 

#define CONFIG_IDENT_STRING              " for MANGO64 uboot-1.3.4-pooh11"

 

부팅 시 표시하는 문구에 uboot-1.3.4-pooh11를 넣어주었습니다.

 

이제 실제로 실행해서 모든 작업을 수행해 보도록 하겠습니다.

 

U-Boot 1.3.4 (Jan 19 2010 - 11:24:18) for MANGO64 uboot-1.3.4-pooh11

CPU:     S3C6410@532MHz

         Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)

Board:   MANGO64

DRAM:    128 MB

Flash:   0 kB

NAND:    256 MB

s3c-nand: ECC uncorrectable error detected

*** Warning - bad CRC or NAND, using default environment

sizeof(default_environment): 311

CFG_ENV_SIZE: 16384, ENV_SIZE: 16380

In:      serial

Out:     serial

Err:     serial

Hit any key to stop autoboot:  0

 

uboot-1.3.4-pooh11가 정확하게 출력되고 있습니다.

 

MANGO64 # print

bootargs=rootfstype=jffs2 root=/dev/mtdblock2 init=/init console=ttySAC1,115200

bootcmd=nand read 50008000 40000 400000;bootm 50008000

mtdpart=40000 400000 4000000

bootdelay=3

baudrate=115200

ethaddr=00:40:5c:26:0a:5b

ipaddr=192.168.11.110

serverip=192.168.11.120

gatewayip=192.168.11.1

netmask=255.255.255.0

stdin=serial

stdout=serial

stderr=serial

Environment size: 350/16380 bytes

 

print를 해보면 수정된 사항이 정확하게 반영되어 있습니다.

 

tftp 51000000 uboot-1.3.4-pooh11.bin

nand erase 0 40000; nand write 51000000 0 40000;

 

위와 같이 NAND에 기록을 하고 NAND mode로 변경 후 부팅을 하였습니다.

 

tftp 51000000 zImage-wifi

nand erase 40000 400000; nand write 51000000 40000 400000;

 

NAND에 커널을 기록하는 부분도 위와 같이 400000까지 기록할 수 있도록 설정하였습니다.

 

tftp 0x51000000 CB64-wifi.jffs2

nand erase 0x400000 0x4000000

nand write.jffs2 0x51000000 0x400000 0x21e0000;

save; save; re

 

파일 시스템까지 기록한 이후에 정상적으로 부팅이 되는 것을 확인했습니다.

 

오늘까지 6번에 걸쳐서 U-Boot에 대한 부분을 살펴보았습니다.

SMDK6410 보드에서 동작하는 U-Boot 소스를 가져다가 하나씩 바꾸어 가면서

망고 64 보드에 적용해가는 과정을 통해서

조금이나마 U-Boot에 대한 이해를 넓힌 듯 생각됩니다.

 

하지만 소스 코드를 보면서 느낀 것이 알아야 할 내용이 너무 많다는 생각입니다.

나중에 U-Boot에 대해서 보다 심도 있게 분석하는 기회가 있었으면 합니다.

 

감사합니다.