초심 프로젝트의 다섯 번째 주제로 직접 타겟 보드에 포팅을 해봄으로써 하드웨어를 이해하도록 한다.

Hardware SMDK2410, EZ-5
Software Toolchain etc

포팅과 관련해서 여기서 언급하지 않는 내용들은 U-BOOT 를 이용한 보드 포팅하기, SMDK 2410 보드 포팅하기 를 참고하기 바란다.
여기서 다룰 것은 크게 세가지이다. 부트로더와 커널, 그리고 파일 시스템의 포팅이다.
각각, u-boot 와 kernel(linux), vpos 를 이용해서 포팅한다. 여기서는 총 3 가지의 툴 체인을 사용한다. 하나의 툴 체인을 사용하면 좋겠지만, 각 소스코드 마다 컴파일러에 의존적인 코드가 있기 때문에 각각의 컴파일 환경을 만들어주어야 한다.

항목 설명 설치 경로
u-boot eldk-arm-linux-x86.iso(1.1.4) 또는 aesoptool_gcc334_glibc233.tar.gz(1.1.5 이상) /usr/local/arm_920 또는 /korea-dokdo
kernel(linux) eldk-arm-linux-x86(2.4.18) /usr/local/arm_920
vpos arm_200701.16.tgz/usr/local/arm

※ 한가지 유의할 점은 eldk-arm-linux-x86.iso 설치시에 설치 경로를 /usr/local/arm_920 으로 해주어야 한다는 점이다.
※ 이것은 U-BOOT 를 이용한 보드 포팅하기, SMDK 2410 보드 포팅하기 에서의 설치 경로와 다르다. .bash_profile 을 다음과 같이 수정한다.

CROSS_COMPILE=arm_920TDI-
PATH=$PATH:$HOME/bin:/usr/local/arm/usr/bin
export PATH CROSS_COMPILE

개발환경 구축하기

앞의 두 개의 문서에서 설명한 내용에서 새롭게 업데이트 된 내용 만을 다룬다.

버전이 1.1.5 이 되면서, U-BOOT 를 이용한 보드 포팅하기 에서 설치했던 arm_920TDI 컴파일러로는 컴파일이 불가능해졌다. 이유는 gcc 버전이 낮기 때문이다.
1.1.4 버전까지는 컴파일이 가능하기 때문에, 굳이 최신버전을 사용하지 않겠다면 예전 방법대로 컴파일하면 된다. 여기서는 현재 최신버전인 1.1.6 을 기준으로 설명한다.
1.1.6 을 컴파일하기 위해서 http://www.aesop-embedded.org/download.html 에서 툴 체인을 다운로드 받는다. 설치 방법은 다음과 같다.

#mkdir /korea-dokdo
#cd /korea-dokdo
#tar xzf aesoptool_gcc334_glibc233.tar.gz -C /korea-dokdo

path 를 걸어주기 위해서 .bash_profile 을 수정한다.

PATH=$PATH:$HOME/bin:/korea-dokdo/aesoptool/gcc-3.3.4-glibc-2.3.3/arm-linux/bin
export PATH

이제 u-boot 를 컴파일하기 위한 준비가 끝났다.

SMDK2410 에 현재 포팅되어 있는 kernel 이 2.4.18 이기 때문에 기존의 툴 체인(arm_920TDI)으로 컴파일해야만 한다.
툴 체인 설치 및 커널 컴파일 방법은 SMDK 2410 보드 포팅하기 를 참고하기 바란다.

vpos 를 위한 툴 체인은 /usr/local/arm 에 설치된다. 다음과 같이 설치한다.

#tar xzf arm_200701.16.tgz -C /usr/local
#cd /usr/local
#ln -s arm arm-sf

path 를 걸어주기 위해 .bash_profile 을 수정한다.

PATH=$PATH:$HOME/bin:/usr/local/arm/bin
export PATH

제목은 host pc 라고 적었지만, redhat 9 에서 tftp 와 dhcp 서비스를 하기 위한 설정에 대해서 설명한다.
여기서는 tftp 의 경우, RPM 으로 설치하고 dhcp 의 경우는 source 설치를 할 것이다.

redhat 9 CD 로부터 tftp 패키지를 찾아 설치한다.

#rpm -ivh tftp-0.32-4.i386.rpm
#rpm -ivh tftp-server-0.32-4.i386.rpm

/etc/xinetd.d/tftp 을 다음과 같이 수정한다.

service tftp
{
        disable = no
        socket_type             = dgram
        protocol                = udp
        wait                    = yes
        user                    = root
        server                  = /usr/sbin/in.tftpd
        server_args             = -s /tftpboot
        per_source              = 11
        cps                     = 100 2
        flags                   = IPv4
}

컴파일 및 설치는 DHCP 서버 구축하기 를 참고하기 바란다.
다음은 /etc/dhcpd.conf 의 설정이다. 참고로 host pc 의 IP 는 166.104.30.15 이고, 타겟 보드의 IP 는 166.104.30.26 이다.

#
# Sample configuration file for ISC dhcpd for Debian
#
# $Id: HardwarePorting,v 1.1 2013/06/07 06:20:43 root Exp root $
#
 
# The ddns-updates-style parameter controls whether or not the server will
# attempt to do a DNS update when a lease is confirmed. We default to the
# behavior of the version 2 packages ('none', since DHCP v2 didn't
# have support for DDNS.)
ddns-update-style none;
 
# option definitions common to all supported networks...
option domain-name "kevin.tcom-dtvro.com";
option domain-name-servers 211.111.136.2;
 
default-lease-time 600;
max-lease-time 7200;
 
# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
#authoritative;
 
# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;
 
# No service will be given on this subnet, but declaring it helps the 
# DHCP server to understand the network topology.
 
#subnet 10.152.187.0 netmask 255.255.255.0 {
#}
 
# This is a very basic subnet declaration.
 
#subnet 10.254.239.0 netmask 255.255.255.224 {
#  range 10.254.239.10 10.254.239.20;
#  option routers rtr-239-0-1.example.org, rtr-239-0-2.example.org;
#}
 
# This declaration allows BOOTP clients to get dynamic addresses,
# which we don't really recommend.
 
#subnet 10.254.239.32 netmask 255.255.255.224 {
#  range dynamic-bootp 10.254.239.40 10.254.239.60;
#  option broadcast-address 10.254.239.31;
#  option routers rtr-239-32-1.example.org;
#}
 
# A slightly different configuration for an internal subnet.
allow bootp;
subnet 166.104.30.0 netmask 255.255.255.0 {
  	range 166.104.30.25 166.104.30.26;
#  option domain-name-servers ns1.internal.example.org;
#  option domain-name "internal.example.org";
  	option routers 166.104.30.1;
  	option broadcast-address 166.104.30.255;
  	default-lease-time 600;
  	max-lease-time 7200;
	group {
		host redwood62.kevin.tcom-dtvro.com {
			hardware ethernet 11:22:33:44:55:66;   # 타겟 보드 MAC Address
			fixed-address 166.104.30.26;     # 타겟 보드 IP
			option root-path "/tftpboot";
		}
	}
}
 
# Hosts which require special configuration options can be listed in
# host statements.   If no address is specified, the address will be
# allocated dynamically (if possible), but the host-specific information
# will still come from the host declaration.
 
#host passacaglia {
#  hardware ethernet 0:0:c0:5d:bd:95;
#  filename "vmunix.passacaglia";
#  server-name "toccata.fugue.com";
#}
 
# Fixed IP addresses can also be specified for hosts.   These addresses
# should not also be listed as being available for dynamic assignment.
# Hosts for which fixed IP addresses have been specified can boot using
# BOOTP or DHCP.   Hosts for which no fixed address is specified can only
# be booted with DHCP, unless there is an address range on the subnet
# to which a BOOTP client is connected which has the dynamic-bootp flag
# set.
#host fantasia {
#  hardware ethernet 08:00:07:26:c0:a5;
#  fixed-address fantasia.fugue.com;
#}
 
# You can declare a class of clients and then do address allocation
# based on that.   The example below shows a case where all clients
# in a certain class get addresses on the 10.17.224/24 subnet, and all
# other clients get addresses on the 10.0.29/24 subnet.
 
#class "foo" {
#  match if substring (option vendor-class-identifier, 0, 4) = "SUNW";
#}
 
#shared-network 224-29 {
#  subnet 10.17.224.0 netmask 255.255.255.0 {
#    option routers rtr-224.example.org;
#  }
#  subnet 10.0.29.0 netmask 255.255.255.0 {
#    option routers rtr-29.example.org;
#  }
#  pool {
#    allow members of "foo";
#    range 10.17.224.10 10.17.224.250;
#  }
#  pool {
#    deny members of "foo";
#    range 10.0.29.10 10.0.29.230;
#  }
#}

컴파일

컴파일 방법은 기존의 문서를 참고하기로 하고, 여기서는 최종 수정한 소스 파일 몇가지를 보이겠다.
다음은 include/configs/smdk2410.h 이다.

/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
 
#define CONFIG_BOOTDELAY        3
/*#define CONFIG_BOOTARGS       "root=ramfs devfs=mount console=ttySA0,9600" */
#define CONFIG_ETHADDR  11:22:33:44:55:66       # 수정
#define CONFIG_NETMASK          255.255.255.0   # 수정
#define CONFIG_IPADDR           166.104.30.26   # 수정
#define CONFIG_SERVERIP         166.104.30.15   # 수정
/*#define CONFIG_BOOTFILE       "elinos-lart" */
/*#define CONFIG_BOOTCOMMAND    "tftp; bootm" */
 
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE    115200          /* speed to run kgdb serial port */
/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX   1               /* which serial port to use */
#endif
 
/*
 * Miscellaneous configurable options
 */
#define CFG_LONGHELP                            /* undef to save memory         */
#define CFG_PROMPT              "FAT81 # "      /* 수정 */
#define CFG_CBSIZE              256             /* Console I/O Buffer Size      */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
#define CFG_MAXARGS             16              /* max number of command args   */
#define CFG_BARGSIZE            CFG_CBSIZE      /* Boot Argument Buffer Size    */
...
...
...
/*-----------------------------------------------------------------------
 * FLASH and environment organization  # 수정 및 추가
 */
 
#define CFG_MAX_FLASH_BANKS     1       /* max number of memory banks */
#define PHYS_FLASH_SIZE         0x02000000
#define PHYS_FLASH_BANK_SIZE    0x02000000
#define PHYS_FLASH_SECT_SIZE    0x00040000
 
#define CFG_MAX_FLASH_SECT      (128)
 
#define CFG_ENV_ADDR            (PHYS_FLASH_1 + 0x40000)
#define CFG_ENV_SIZE            0x40000
#define CFG_ENV_SECT_SIZE       0x40000
 
/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT    (5*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT    (5*CFG_HZ) /* Timeout for Flash Write */
 
#define CFG_ENV_IS_IN_FLASH     1
 
#endif  /* __CONFIG_H */

다음은 board/smdk2410/flash.c 이다.

unsigned long flash_init (void)
{
        int i;
        ulong size = 0;
 
        for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
                switch (i) {
                case 0:
                        flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
                        flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
                        break;
                case 1:        # 수정
                        break;
                default:
                        panic ("configured too many flash banks!\n");
                        break;
                }
                size += flash_info[i].size;
        }
 
        /* Protect monitor and environment sectors
         */
        flash_protect ( FLAG_PROTECT_SET,
                        CFG_FLASH_BASE,
                        CFG_FLASH_BASE + monitor_flash_len - 1,
                        &flash_info[0] );
 
        flash_protect ( FLAG_PROTECT_SET,
                        CFG_ENV_ADDR,
                        CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] );
 
        return size;
}

다음은 lib_arm/armlinux.c 이다.

		SHOW_BOOT_PROGRESS (10);
 
		print_image_hdr (hdr);   /* 앞에서 ramdisk.fat 생성시에 mkimage 를 이용해서 만든 커널 헤더를 읽어서 램디스크 정보 출력  */
 
		data = addr + sizeof (image_header_t);
		len = ntohl (hdr->ih_size);
 
#ifdef CONFIG_HAS_DATAFLASH    /* 실행 안됨 */
		if (addr_dataflash (addr)) {
			read_dataflash (data, len, (char *) CFG_LOAD_ADDR);
			data = CFG_LOAD_ADDR;
		}
#endif
 
		memcpy((char *)0x30800000, (char *)data, len);        // 추가할 부분 (data : 0x140040, len : 0x34ec24)
 
		if (verify) {
			ulong csum = 0;
 
			printf ("   Verifying Checksum ... ");
			csum = crc32 (0, (char *) data, len);
			if (csum != ntohl (hdr->ih_dcrc)) {
				printf ("Bad Data CRC\n");
				SHOW_BOOT_PROGRESS (-12);
				do_reset (cmdtp, flag, argc, argv);
			}
			printf ("OK\n");
		}

SMDK 2410 보드 포팅하기 를 참고하기 바란다.

압축을 풀고 컴파일하면 된다.

#tar xzf vpos.tar.gz
#make clean
#make

에러없이 컴파일 되었다면, images 디렉토리에 elf 와 binary 파일이 생성되었을 것이다.
vpos.bin 파일을 SMDK2410 test program 을 이용해서 NOR Flash 0x0 번지에 write 하면 된다.

  • computer/rtcclab/hardware_porting.txt
  • Last modified: 3 years ago
  • by likewind