'커널 포팅'에 해당되는 글 10건

  1. 2009.07.16 2.6.28 커널로 갈아타기 - EZ-X7 시리얼 포팅 (2)
  2. 2009.07.11 2.6.28 커널로 갈아타기 - ARM 커널 부팅 추적
  3. 2009.07.07 2.6.28 커널로 갈아타기 - 부팅 초기 디버그 메시지 표출 (1)
  4. 2009.06.02 2.6.28 커널로 갈아타기 - ARM 커널과 머신 아키텍쳐 번호
  5. 2009.05.29 2.6.28 커널로 갈아타기 - zImage 와 시리얼 포트 (1)
  6. 2009.05.26 2.6.28 커널로 갈아타기 - arm 커널 부팅과 시리얼 포트
  7. 2009.05.18 2.6.28 커널로 갈아타기 - 커널 최초 컴파일 시험 (3)
  8. 2009.05.10 2.6.28 커널로 갈아타기 - 개발 환경
  9. 2009.05.07 2.6.28 커널로 갈아타기 - 첫번째 목표
  10. 2009.05.06 2.6.28 커널로 갈아타기 - 커널 포팅이란?
2009.07.16 22:10

2.6.28 커널로 갈아타기 - EZ-X7 시리얼 포팅

부트로더 버전 확인


PXA270 프로세서 보드인 EZ-X7 시리얼 포팅입니다.

EZ-X7 부트로더를 한번 확인해 봅시다.

제 것은 이렇게 나왔습니다. 

 

[A014_010_boot_loader_version.png]

오 예~~

좋네요 V2.3.04 군요

 

환경을 맞추어 봅시다.

set 명령을 사용해서

EZBOOT>set
^^;
   1) mac address            : 00:FA:07:78:27:04
   2) local ip               : 192.168.10.188
   3) local netmask          : 255.255.0.0
   4) local gateway          : 192.168.10.1
   5) server ip              : 192.168.10.61
   6) zImage      file name  : zImage.ez-pxa270
   7) ram disk    file name  : ramdisk-1.11-16M.gz
   8) boot loader file name  : ezboot.ez-pxa270
   9) logo image  file name  :
  10) auto execute full name :
  11) autoboot wait time     : 3
  12) copy ramdisk [Y/N]     : Y
  13) arm kernel arch number : 1010
  14) nand part (B,C,L,K,R,A): 0,1,0,3,5,55
  15) watchdog  (sec, off=0) : 0
  16) KCMD 1 : mem=64M
  17) KCMD 2 : initrd=0xA0800000,5M root=/dev/ram ramdisk=16384
  18) KCMD 3 : console=ttyS2,115200
  19) KCMD 4 : video=ezfb:panel:2
  20) KCMD 5 :
  21) KCMD 6 :

  L)  Load default
      LF) load KCMD2 root=flash
      LR) load KCMD2 root=ramdisk
  M)  generlate Mac address
  S)  Save to flash
  P)  aPply & exit
  Q)  Quit

  Select >>

자신의 네트워크 상황에 맞도록 2,3,4,5 항을 수정하십시오.
위 예시는 제 보드의 네트워크 설정입니다.

그리고 환경 저장을 하시고

rst 명령을 사용하거나 전원을 껐다가 켜서 다시 보드를 부팅 시킵니다.

커널 소스 클리어


이제 싸~~악… 소스를 클리어 하는 것이 제일 좋겠죠?

이제 반복적이죠?

기억 나시죠 ? 다음 명령들

  
   [root@localhost linux]# make mrproper
   [root@localhost linux]# make distclean

예..

이제 소스 쌱~~ 청소 되었습니다.


커널 컴파일 환경 설정 준비


자 이제 이전에 설정된 환경을 찾아 보죠..

어디서요?

linux/arch/arm/configs/

에서요..

일단 이곳에서 PXA270용을 찾아 봅시당.

아무래도 인텔(지금은 마벨)에서 나왔던 평가 보드가 처음 선택에는 유리할지도...

mainstone_defconfig 란 이름이네요

밑져야 본전

이놈을 가지고 시작해 봅시다.

여기서 잠깐!

이전 강좌를 보지 않으신 분들이 가장 먼저 해야 하는 것은
Makefile을 약간 손보아야 합니다.

커널소스 linux\Makefiel 에서 193 라인 쯤에 가면

크로스 컴파일을 위한 처리 부분이 있습니다.

193 ARCH            ?= $(SUBARCH)
194 CROSS_COMPILE   ?=

이 부분을 arm 용 크로스 컴파일이 될 수 있도록 다음과 같이 고칩니다.

193 ARCH            ?= arm
194 CROSS_COMPILE   ?= arm-linux-


이 부분에 대한 약간(?)의 설명은 2410 부분의 강좌를 참조해 주세요

2410부터 따라한 분들은 이미 되어 있겠죠?
 

자 이제 커널 컴파일 옵션 적용을 해 봅시다.

make mainstone_defconfig

이렇게 하면 한방에

mainstone 컴파일 옵션 설정 상태로 만들어 버립니다.

[root@localhost linux]# make mainstone_defconfig
HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  HOSTCC  scripts/basic/hash
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/kxgettext.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/lex.zconf.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
#
# configuration written to .config
#
[root@localhost linux]#


시리얼 출력을 하기 위한 커널 소스 패치


이쯤 되면 시리얼 출력을 하기 위해서 다음 두 가지를 처리해야 한다는 것을 인식하시겠죠?

1)    시리얼 포트
2)    머신 아키텍쳐 번호

EZ-X7 의 콘솔용 시리얼 포트는 몇 번일까요?

이지부트 소스를 보면 알 수 있죠..
아니면 이지부트에서 전달하는 커널 커맨드 console= 에 어떤 포트가 지정되어 있는가를 보면 알 수 있죠..

console=ttyS2,115200

이렇게 되어 있네요?

예 2 번째 포트를 사용합니다.

그런데 …

PXA 커널 옵션을 들여다 보면 삼성 프로세서 처럼 시리얼 포트를 컴파일 환경 설정 메뉴에서 지정할 수 없습니다.

즉 소스를 패치 해야 한다는 겁니다.

의심스러우시면 S3C2440이나 S3C2410 에서 했던 것처럼 커널 컴파일 환경 설정 메뉴를 따라 가 보시기 바랍니다.

어찌되었든 첫번째 압축 해제를 위해서 수정해야 할 소스는 여기 입니다.

arch/arm/mach-pxa/include/mach/uncompress.h

아주 심플하게 필요한 매크로 함수만 정의되어 있는 소스가 보이죠?

소스상에서 보면

static volatile unsigned long *UART = FFUART;

를 보면 알겠지만

메인스톤은 EZ-X7과 달리 UART0 으로 압축 해제 메시지를 처리 하고 있습니다.

그런데 저희는 UART2 로 해야죠? 이건 이름이 STUART 입니다.

그런데 소스상에 arch_decomp_setup 함수에 비슷하게 있는데 조건 문이 보이죠?

그래서 그냥 다음과 같이 수정해 버립니다.

static inline void arch_decomp_setup(void)
{
//      if (machine_is_littleton())
                UART = STUART;
}



자 시리얼 포트를 조정했으니
정상적으로 부팅이 진행되도록 머신 아키텍쳐 번호를 알아내야 합니다.

리눅스 소스에 있는 파일에서 찾아 봅시다.

linux/arch/arm/tools/mach-types

422 번째 라인을 보면 메인스톤이 보일 겁니다.

mainstone    MACH_MAINSTONE    MAINSTONE   406

예…

머신 아키텍쳐 번호는 406 번 되겠네요

이 값을 나중에 이지부트에서 설정하면 됩니다. 


커널 컴파일 및 tftp 복사


이제 커널 컴파일을 해야 겠죠?

[root@localhost linux]# make zImage

별 무리 없이 컴파일 될 겁니다.

한가지 흠이라면 약간의 시간이 걸리죠 ㅋㅋ

이제 생성된 zImage 를 tftp 디렉토리에 복사합니다.

[root@localhost linux]# cp arch/arm/boot/zImage /tftpboot/zImage.ez-pxa270

이지부트 머신 아키텍쳐 번호 수정


부트로더에서 set 명령을 이용하여 아키텍쳐 번호를 406으로 수정합니다. 

 

[A014_020_ezboot_set.png]

S 로 저장하고 Q 로 빠져 나옵니다. 



커널 다운 로드 와 부팅


tfk 명령을 통해서 커널 이미지를 다운 받습니다.

 
 
[A014_030_kernel_download.png]

rst명령을 사용하여 부팅합니다.


 

자 어떻게 될까요?

두근 두근…..

  

[A014_040_kernel_fail.png]

흑흑흑..

도대체 한번에 넘어가는 적이 없군요…

이번엔 또 무슨 문제 일까요?


디버그 메시지 처리



arch/arm/mach-pxa/include/mach/debug-macro.S

여기서  addruart 매크로는 rx 에 전달된 값에 디버그용 시리얼 포트 주소값을 전달하게 하는 매크로입니다.

그러므로 여기서 주소를 지정해 주어야 합니다.

원래는 이렇게 되어 있습니다.


               .macro  addruart,rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
                moveq   \rx, #0x40000000                @ physical
                movne   \rx, #io_p2v(0x40000000)        @ virtual
                orr     \rx, \rx, #0x00100000
                .endm



이걸 다음과 같이 주소를 바꿉니다.
STUART  는 주소가 0x40700000 이므로


               .macro  addruart,rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
                moveq   \rx, #0x40000000                @ physical
                movne   \rx, #io_p2v(0x40000000)        @ virtual
                orr     \rx, \rx, #0x00700000
                .endm


로 바꾸어 줍니다.

그리고 커널 컴파일 후 다시 실행해 봅니다.

역시~~ 마찬가지

도대체 왜 이럴까요?

X5 의 경험을 되살려 보자


X5의 경험을 되살려 봅시다.

아무래도

3가지를 점검할 필요가 있겠죠?

부트파라메터가 전달되고 있는가? 가 첫번째 점검 사항이죠?

arch/arm/mach-pxa/mainstone.c 파일에 다음 내용이 있는 가를 보는 거죠

.boot_params    = 0xa0000100,   /* BLOB boot parameter setting */

있군요..  쩝

그러면 LED와 프레임 버퍼를 꺼 봅시당.

make menuconfig 를 수행해서 다음 부분을 찾아 설정해 봅시다.

Kernel Features  --->
               [ ] Timer and CPU usage LEDs

Device Drivers  --->
              Graphics support  --->
                         < > Support for frame buffer devices  --->


위가 어떤 의미인지는 알겠지요?

다운로드 하고 다시 부팅해 봅시당..

그..러..나

결과는 마찬가지 ..


휴우~~~~ 거저 먹는 법이 없어요…


그래도 역시 인터럽트..


그렇다고 포기 하면 안되지요…

이런 경우 추정 가능한 원인은 인터럽트라고 말씀 드렸죠?

그렇다면 메인스톤 보드 역시 의심해 봐야 겠죠…

arch/arm/mach-pxa/mainstone.c 파일은 메인스톤의 설정 파일입니다.

이 파일안에서 mainstone_init_irq() 함수에서 기본 PXA270 인터럽트 설정 부분을 제외한 모든 부분을 주석 처리해 봅니다.

 

[arch/arm/mach-pxa/mainstone.c]
  

171 static void __init mainstone_init_irq(void)
    172 {
    173         int irq;
    174
    175         pxa27x_init_irq();
    176
    177         /* setup extra Mainstone irqs */
    178 //      for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
    179 //              set_irq_chip(irq, &mainstone_irq_chip);
    180 //              set_irq_handler(irq, handle_level_irq);
    181 //              if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
    182 //                      set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
    183 //              else
    184 //                      set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
    185 //      }
    186 //      set_irq_flags(MAINSTONE_IRQ(8), 0);
    187 //      set_irq_flags(MAINSTONE_IRQ(12), 0);
    188
    189 //      MST_INTMSKENA = 0;
    190 //      MST_INTSETCLR = 0;
    191
    192 //      set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
    193 //      set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
    194 }

그리고 컴파일 하고 다시 재 부팅…

> COM Port              : COM4
> Baud Rate             : 115200
> Data Bits             : 8
> Parity                : None
> Stop Bits             : 1
> Hardware Flow Control : None
> Software Flow Control : None

Connected to COM4...



WELCOME EZBOOT V2.3.05 (FALINUX Co.,Ltd) ......PXA270(EZ-PXA270) (520MHz)
Program by You Young-chang, Oh Jae-Kyong, Jang Hyung-Gi
Last Modify May  4 2009

  Detect ES29LV400_B Flash : vid=4A pid=22BA
  SIZE 4-Mbits [512-Kbytes]

  Detect Samsung NAND 64M 3.3V 8-bit Flash : vid=EC pid=76
  SIZE 64-Mbytes (page=512, block=16K)

  LCD setup 640x480
  draw logo bitmap Image .....
    File  Size  -  921654 Bytes
    Image Size  -  640 x 480


Quickly Autoboot [ENTER] / Goto BOOT-MENU press [space bar]......

Copy Kernel Image .....
Starting kernel [MARCH 406]...
kernel command [EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200 video=ezfb:panel:2   ip0=192.168.10.188 mac=00:FA:07:78:27:04 netmask=255.255.0.0 gw=192.168.10.1 host=192.168.10.61 nandparts=3,8,53 ]
Uncompressing Linux.................................................................................... done, booting the kernel.
Linux version 2.6.28.10 (root@localhost.localdomain) (gcc version 3.4.3) #5 Sat Jul 11 04:39:03 EDT 2009
CPU: XScale-PXA270 [69054117] revision 7 (ARMv5TE), cr=0000397f
CPU: VIVT data cache, VIVT instruction cache
Machine: Intel HCDDBBVA0 Development Platform (aka Mainstone)
Memory policy: ECC disabled, Data cache writeback
Run Mode clock: 208.00MHz (*16)
Turbo Mode clock: 520.00MHz (*2.5, active)
Memory clock: 104.00MHz (/2)
System bus clock: 104.00MHz
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200 video=ezfb:panel:2   ip0=192.168.10.188 mac=00:FA:07:78:27:04 netmask=255.255.0.0 gw=192.168.10.1 host=192.168.10.61 nandparts=3,8,53
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 62212KB available (2384K code, 187K data, 84K init)
SLUB: Genslabs=12, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Calibrating delay loop... 519.37 BogoMIPS (lpj=2596864)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 288 bytes
NET: Registered protocol family 16
Mainstone configured to boot from processor-flash
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97 (double precision)
JFFS2 version 2.2. (NAND) 짤 2001-2006 Red Hat, Inc.
msgmni has been set to 121
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
pxa2xx-uart.0: ttyS0 at MMIO 0x40100000 (irq = 22) is a FFUART
pxa2xx-uart.1: ttyS1 at MMIO 0x40200000 (irq = 21) is a BTUART
pxa2xx-uart.2: ttyS2 at MMIO 0x40700000 (irq = 20) is a STUART
console [ttyS2] enabled
smc91x: not found (-19).
Uniform Multi-Platform E-IDE driver
ide-gd driver 1.18
mice: PS/2 mouse device common for all mice
TCP cubic registered
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
XScale iWMMXt coprocessor detected.
VFS: Cannot open root device "ram" or unknown-block(1,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)

음하하.. EZ-PXA270 보드도 가뿐하게 성공…

이것 역쉬 옮겨 봅니다.


이제까지 작업한 환경 설정을 저장하고

[root@localhost linux]# cp .config arch/arm/configs/ezpxa270_defconfig

커널을 클리어 합니다.
   
[root@localhost linux]# make clean


새로 추가된 파일이 있는가 확인 합니다.

[root@localhost linux]# svn st


새로 생성된 것중 서브버전에 추가 할 파일을 추가 합니다.

[root@localhost linux]# cd arch/arm/configs/
[root@localhost configs]#svn add ezpxa270_defconfig


서브 버전에 커밋 합니다.

[root@localhost configs]# cd ../../..
[root@localhost linux]#  svn ci -m "EZ-PXA270 serial first portign sucess"



우후~~   끝났당…


Trackback 0 Comment 2
  1. 이상한데... 2010.01.07 19:45 신고 address edit & del reply

    저기 중간에 커널 패닉 뜨셨는데 성공이라니요..???

  2. 나그네 2011.05.25 11:10 신고 address edit & del reply

    메시지를 다 읽어보진 않았지만 커널은 정상적으로 로딩된거 같네요
    파일시스템 마운트경로만 걸어주면 잘 작동할듯

2009.07.11 16:18

2.6.28 커널로 갈아타기 - ARM 커널 부팅 추적

ARM 커널 부팅 관련 파일들

 

커널 추적을 위한 디버그 함수는 준비 되었습니다.

그런데..

여러분은 어디서부터 추적해야 할지 암담하죠?

예…

저도 처음엔 그랬습니다.

지금요?

흑…

지금도 그래요…

그러나

이번 기회에 심플하게 어떤 파일들이 부팅 초기에 관여하는지를 초 간단 버전으로 보겠습니다.

정답을 미리 알려 드리는 것이 편하겠지요?

arch/arm/kernel/head.S
arch/arm/kernel/head-common.S
init/main.c

이 세가지 파일이 뒤져야 하는 핵심입니다.

그 외에 항상 보아야 하는 것은 플랫폼 셋업 파일이죠..

현재 IDP 보드로 살펴 보고 있으니

arch/arm/mach-pxa/idp.c

이 파일이 되겠습니다.

 

추적을 위한 어셈블러용 매크로 선언

커널이 어떤 위치를 통과 하는지 구경하려면 지정된 위치 정보를 문자열로 시리얼을 통해서 출력하면 좋겠죠?

그래서 이전에 시험했던 루틴을 조금 손봐서 만들어 봤습니다.

#define STRINGIFY(x)                    #x
#define TOSTRING(x)                     STRINGIFY(x)

#define TRACE_LINE(ra,rb,rc)            mov     ra,r0;                  \
                                        mov     rb,r1;                  \
                                        mov     rc,r2;                 \
                                                                        \
                                        adr     r0,9998f;               \
                                        bl      printascii ;            \
                                                                        \
                                        mov     r2,rc;                 \
                                        mov     r1,rb;                  \
                                        mov     r0,ra;                  \
                                                                        \
                                        b       9999f;                  \
                                9998: ;                                 \
                                        .ascii  "\n>>TRACE:";           \
                                        .ascii  __FILE__;               \
                                        .ascii  ":";                    \
                                        .asciz  TOSTRING(__LINE__);     \
                                        .align;                         \
                                9999: ;


이걸 쓸데는 TRACE_LINE 을 사용하고 ra,rb,rc 파라메터는
출력시 파괴되는 R0,R1,R2를 임시로 대피할 레지스터를 지정하면 됩니다.

부팅 초기에는 R8,R11,R12 레지스터를 추천합니다.

요건 어디에 놓으면 좋을까요?

헤더파일에 넣어 놓으면 좋지 않을까요?

그래서 다음 파일에 넣어 둡니다.

arch/arm/include/asm/ptrace.h

다음은 편집된 내용입니다.

 

[arch/arm/include/asm/ptrace.h]
 
  157 #define STRINGIFY(x)                    #x
    158 #define TOSTRING(x)                     STRINGIFY(x)
    159
    160 #define TRACE_LINE(ra,rb,rc)            mov     ra,r0;                  \
    161                                         mov     rb,r1;                  \
    162                                         mov     rc,r2;                 \
    163                                                                         \
    164                                         adr     r0,9998f;               \
    165                                         bl      printascii ;            \
    166                                                                         \
    167                                         mov     r2,rc;                 \
    168                                         mov     r1,rb;                  \
    169                                         mov     r0,ra;                  \
    170                                                                         \
    171                                         b       9999f;                  \
    172                                 9998: ;                                 \
    173                                         .ascii  "\n>>TRACE:";           \
    174                                         .ascii  __FILE__;               \
    175                                         .ascii  ":";                    \
    176                                         .asciz  TOSTRING(__LINE__);     \
    177                                         .align;                         \
    178                                 9999: ;
    179
    180 #endif
    181


arch/arm/kernel/head.S  추적

 

이 파일은 커널이 가장 처음 시작되는 부분이죠..

뭐 하는 파일이냐구요?

프로세서를 초기화 하는 것과 커널용 1차 MMU테이블 작성이 주된 일이죠

그럼 멈춘 원인을 발견하기 위해서는 어떤 부분을 찍어가야 할까요?

솔찍하게 말씀 드리면

이 글을 쓰는 시점에 저는 대략 원인을 알고 있습니다.

그런데 정답을 알려 주면 이전 강좌에 기껏 말한

커널 추적 디버그 함수를 쓸 일이 없잖아요..

그래서

중요 포인터에 커널 표출 메시지를 삽입하고 통과 되지 않는 부분을 알려 주려 하는 것이지요

이 부분에서 통과 하지 않으면 이 부분이 아마도 원인일 것이다.

이런식으로요…

그리고 커널이 어떤 부팅 흐름을 가지는 가도 보여 주려는 것 이지요…

 

●  ENTRY(stext)

 

이 부분은 커널 시작되면서 진입하는 위치죠.

진입 여부는 이전 강좌에 표출하는 예제를 통해 확인 되었죠.

이 부분은 다음과 같은 처리를 합니다.

 

1) 프로세서 타입을 얻어 옵니다.
2) 머신 정보를 확인합니다.
3) 파라메터 테이블인 ATAG의 정렬상태와 같은 오류를 검사합니다.
4) 가장 기본적인 MMU 테이블을 만듭니다.

 

이게 어디까지 있냐면


 

bl __create_page_tables

 

이 함수가 호출되는 곳 까지 입니다.

그래서 이 부분 다음에 다음 같은 메시지를 끼어 넣고 표출해 봅니다.

 이전에 선언된 TRACE_LINE 이라는 매크로를 써 넣습니다.

다음은 TRACE_LINE을 넣은 head.S 처음 부분입니다.

 

   
     78         .section ".text.head", "ax"
     79 ENTRY(stext)
     80
     81         TRACE_LINE(r8,r11,r12)
     82
     83         msr     cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
     84                                                 @ and irqs disabled
     85         mrc     p15, 0, r9, c0, c0              @ get processor id
     86         bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
     87         movs    r10, r5                         @ invalid processor (r5=0)?
     88         beq     __error_p                       @ yes, error 'p'
     89         bl      __lookup_machine_type           @ r5=machinfo
     90         movs    r8, r5                          @ invalid machine (r5=0)?
     91         beq     __error_a                       @ yes, error 'a'
     92         bl      __vet_atags
     93         bl      __create_page_tables
     94
     95      TRACE_LINE(r8,r11,r12)
     96
     97         /*
     98          * The following calls CPU specific code in a position independent
     99          * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
    100          * xxx_proc_info structure selected by __lookup_machine_type
    101          * above.  On return, the CPU will be ready for the MMU to be
    102          * turned on, and r0 will hold the CPU control register value.
    103          */
    104         ldr     r13, __switch_data              @ address to jump to after
    105                                                 @ mmu has been enabled
    106         adr     lr, __enable_mmu                @ return (PIC) address
    107         add     pc, r10, #PROCINFO_INITFUNC
    108
    109         TRACE_LINE(r8,r11,r12)
    110
    111 ENDPROC(stext)


커널이 실행되면 109 번 행에 넣은 부분은 절대로 출력 되면 안됩니다.

위 루틴은 프로세서 초기화를 수행하고 107 번 라인 부분이 수행 된 후

__mmap_switched  를 호출하기 때문입니다.


81 문장 라인번호를 출력하고 95번 행을 출력하지 않는다면 이 경우는 대부분 머신 ID 설정의 문제입니다.

이제 커널을 컴파일 하고 보드에 다운로드 하고 실행하면 다음과 같은 메시지가 나옵니다.

>>TRACE:arch/arm/kernel/head.S:81
>>TRACE:arch/arm/kernel/head.S:95

결국 여기까지는 정상적으로 진행 된다는 것이죠….


 

arch/arm/kernel/head-common.S   추적

head.S에서 기본적인 초기화 및 mmu가 활성화 된 이후에 head-common.S 로 부팅은 진행됩니다.

이 파일에 __mmap_switched  가 수행되는 데 이 루틴은 start_kernel 이라는 C 함수를 호출하기 전 C 함수 호출이 가능하도록 스택이나 BSS 와 같은 메모리 구조들을 정리합니다. 그리고 start_kernel 함수를 호출합니다.

start_kernel 함수 호출 전까지 정상적으로 진행되는지를 체크하기 위해서 다음과 같은 처리를 합니다.   

39 __mmap_switched:
     40
     41         TRACE_LINE(r8,r11,r12)
     42
     43         adr     r3, __switch_data + 4
     44
     45         ldmia   r3!, {r4, r5, r6, r7}
     46         cmp     r4, r5                          @ Copy data segment if needed
     47 1:      cmpne   r5, r6
     48         ldrne   fp, [r4], #4
     49         strne   fp, [r5], #4
     50         bne     1b
     51
     52         mov     fp, #0                          @ Clear BSS (and zero fp)
     53 1:      cmp     r6, r7
     54         strcc   fp, [r6],#4
     55         bcc     1b
     56
     57         ldmia   r3, {r4, r5, r6, r7, sp}
     58         str     r9, [r4]                        @ Save processor ID
     59         str     r1, [r5]                        @ Save machine type
     60         str     r2, [r6]                        @ Save atags pointer
     61         bic     r4, r0, #CR_A                   @ Clear 'A' bit
     62         stmia   r7, {r0, r4}                    @ Save control register values
     63
     64         TRACE_LINE(r8,r11,r12)
     65
     66         b       start_kernel
     67 ENDPROC(__mmap_switched)
     68


이제 커널을 컴파일 하고 보드에 다운로드 하고 실행하면 다음과 같은 메시지가 나옵니다.

>>TRACE:arch/arm/kernel/head.S:81
>>TRACE:arch/arm/kernel/head.S:95
>>TRACE:arch/arm/kernel/head-common.S:41
>>TRACE:arch/arm/kernel/head-common.S:64


결국 여기까지는 정상적으로 진행 된다는 것이죠….

추적을 위한 C 매크로 선언

C 에서 printk를 사용하지 않고 어셈블러에서 제공하는 시리얼용 디버그 용 함수를 사용하여 위치 정보를 문자열 출력하는  매크로 다음과 같이 만들었습니다.


extern void printascii( char *str );

#define STRINGIFY(x)                    #x
#define TOSTRING(x)                     STRINGIFY(x)

#define TRACE_LINE      printascii( "\n>>TRACE " __FILE__ ":");\
                                           printascii( __FUNCTION__ );\
                                           printascii( ":" TOSTRING(__LINE__) );


 이걸 어디에 놓으면 좋을까요?

다음 파일에 넣어 둡니다.

include/linux/init.h

다음은 편집된 내용입니다.

[include/linux/init.h]

   

160
    161 #ifndef __ASSEMBLY__
    162
    163 extern void printascii( char *str );
    164
    165 #define STRINGIFY(x)    #x
    166 #define TOSTRING(x)     STRINGIFY(x)
    167
    168 #define TRACE_LINE      printascii( "\n>>TRACE " __FILE__ ":");\
    169                         printascii( __FUNCTION__ );\
    170                         printascii( ":" TOSTRING(__LINE__) );
    171

init/main.c 추적 

 head-common.S  파일에 있는 __mmap_switched  가 마지막으로 호출하는 것은 init/main.c  파일에 start_kernel() 함수 입니다.

이 함수까지 오는지를 앞에서 만든 매크로를 활용하여 확인해 봅시다.

542 asmlinkage void __init start_kernel(void)
    543 {
    544         char * command_line;
    545         extern struct kernel_param __start___param[], __stop___param[];
    546
    547         TRACE_LINE
    548
    549         smp_setup_processor_id();
    550

 

커널을 올리고 부팅하면 다음과 같은 메시지가 표출 됩니다.

>>TRACE:arch/arm/kernel/head.S:81
>>TRACE:arch/arm/kernel/head.S:95
>>TRACE:arch/arm/kernel/head-common.S:41
>>TRACE:arch/arm/kernel/head-common.S:64
>>TRACE init/main.c:start_kernel:547


여기까지는 정상적으로 동작합니다.

아마도 인터럽트 , 디바이스 드라이버, 커널 커맨드에서 콘솔 지정에 문제가 일 가능성이 높습니다.

아예 부팅이 되지 않고 있는 것이 아니니까요 ..

더 추적하고 싶지만…

갈길이 바쁘니…

추적은 여기서 중지 합니다.

추적 방법을 알려 드렸으니 여러분 나름대로 쭈욱 찾아가 보는 것도 좋죠…

아니면 이번 세미나 때 제가 ARM 커널 부팅 추적을 할 예정이므로 그때
다시 한번 들어 보시는 것도 괜찮을 듯 합니다
Trackback 0 Comment 0
2009.07.07 02:53

2.6.28 커널로 갈아타기 - 부팅 초기 디버그 메시지 표출

너무 오래동안 진행이 멈추었던 점 용서해 주십시오

먹고 사니즘 땜시 스케쥴에 나름대로 어려움이 있었답니다.  

ARM 커널 부팅 과정 디버깅 메시지 시리얼로 보기

서 손을 보아야 할지
고민 고민 했습니다.

이렇게 부팅이 되지 않는 경우에는 삽질이라는 과정이 필요한데

제 나이쯤 되면 이런 삽질이 영 달갑지 않습니다. 

하드웨어에 도통한 분들이 스코프 들기 싫은 것처럼

커널 포팅에 도통한 저는 디버그 메시지 찍어 가면서
어디가 문제인지 알아 보는 것이 정말 싫거든요…
(하하 건방에 용서를 굽실 굽실… )

더구나 비축 분도 떨어졌죠… 요즘 쪼메 바빴거든요..
여러모로 암담합니다.

어찌되었든 커널 메시지를 뿌리는 printk 가 동작이 제대로 동작하지 않는 상황
즉 console 디바이스가 동작 하지 않는 경우에는 커널 부팅을 추적할 때
어떻게 해야 할지 막막 하지요…

그..러..나

ARM 리눅스 커널 만든 사람들 역시 이런 고생을 하지 않았겠습니까?

그들도 우리와 같은 개발자인데 말이죠

그런 이유로 이런 부분의 문제점을 해결하기 위한 장치를 마련 했답니다.

여러분은 이 방법을 알아야 디버깅이 가능합니다.

또한 커널이 압축이 해제 된 이후 어떻게 동작하는지 추적하려면

시리얼로 메시지를 표출하는 방법에 대하여 반드시 알아야 합니다.

제가 이 방법을 알려 드리겠습니다.

 

커널 컴파일 옵션 설정

이 과정은 이전에 설명한 부분인데 다시 한번 강조 해야 할 듯 합니다.

우선 커널 컴파일 옵션에서 다음과 같이 체크되어 있어야 합니다.

Kernel hacking  --->
  [*] Kernel low-level debugging functions

 

[A015_010_kernel_hacking_option_580.png]

 

 


[A015_020_kernel_hacking_low_level_option.png] 

 debug.S  관련 소스 수정

 

ARM 에서는 커널 부팅 중 console 장치가 아닌 시리얼 장치를 이용하여 부팅 단계에서 문자열을 출력 하고자 하다면 다음 파일이 이를 처리해 주는 루틴을 가지고 있습니다.

arch/arm/kernel/debug.S

이 파일에는 다음과 같은 함수가 선언되어 있습니다.

 

printhex8 : R0 또는 첫번째 매계변수의 값을 8 자리 16진수 문자열로 표시
printhex4 : R0 또는 첫번째 매계변수의 값을 4 자리 16진수 문자열로 표시
printhex2 : R0 또는 첫번째 매계변수의 값을 2 자리 16진수 문자열로 표시
printascii : R0 또는 첫번째 매계변수의 값이 가리키는 문자열 주소를 이용하여  \0 문자로 끝나는 문자열 표시 
printch : R0 또는 첫번째 매계변수의 값에 해당하는 문자를 표시


이 함수들은 어셈블러 루틴에서 호출 할 수도 있고
C 함수로도 호출이 가능합니다.

 

이 함수들이 호출하는 매크로가 몇 개 있는데 각 보드마다 이 부분을 수정해 주어야 합니다.

 

다음과 같은 이름을 가지고 있고 처리하는 기능은 다음과 같습니다.

 

addruart  :  UART 장치의 선두 주소를 얻어 옵니다.
waituart     :  UART가 출력이 가능해 질 때까지 기다립니다.
senduart   :  UART 에 한 문자를 출력합니다.
busyuart  :  UART가 문자를 완전히 출력할 때까지 기다립니다.

 

이 함수는 어셈블러 매크로로 구성되고 개발자가 수정할 수 있습니다.


매크로는 각각 사용될 레지스터를 지정하면 됩니다.

 

우리는 우선적으로 adduart 매크로를 수정해야 합니다.

 

왜냐하면 설정된 IDP 보드는 시리얼 포트 0을 사용하지만 EZ-X5는 포트 2를 사용해야 하기 때문입니다.
 

그렇다면 이렇게 각각 다른 포트를 지정하는 것은 어디에 있을까요?

 

pxa 계열은 다음 헤더 파일에 선언하고 있습니다.

arch/arm/mach-pxa/include/mach/debug-macro.S

이 파일을 보면 addruart 매크로를 정의하고 있는데 rx 에 설정된 레지스터에 디버그용 시리얼 포트 주소 값을 설정합니다.

이때 주의 깊게 보아야 하는 것이 MMU 가 동작할 경우와 그렇지 않을 경우를 자동으로 설정하고 있는데 이때 사용되는 매크로가 io_p2v 라는 겁니다.

여기서는 그리 고민하지 않아도 됩니다만 그냥 커널의 어드레스 변환 함수로 한번쯤 기억하라고 말씀 드리는 겁니다.

어찌되었든 여기서 주소를 지정해 주어야 합니다.

원래는 이렇게 되어 있습니다.

              

               .macro  addruart,rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
                moveq   \rx, #0x40000000                @ physical
                movne   \rx, #io_p2v(0x40000000)        @ virtual
                orr     \rx, \rx, #0x00100000
                .endm

 

               .macro  addruart,rx
                mrc     p15, 0, \rx, c1, c0
                tst     \rx, #1                 @ MMU enabled?
                moveq   \rx, #0x40000000                @ physical
                movne   \rx, #io_p2v(0x40000000)        @ virtual
                orr     \rx, \rx, #0x00700000
                .endm

 

 head.S 와 디버그 문자열 출력 테스트

 

압축이 풀린 커널의 소스 중 가장 먼저 호출되는 위치는 다음 파일에 있습니다.

arch/arm/kernel/head.S

이 파일에 다음 부분이 커널의 최초 진입 점이죠

/*
 * Kernel startup entry point.
 * ---------------------------
 *
 * This is normally called from the decompressor code.  The requirements
 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
 * r1 = machine nr, r2 = atags pointer.
 *
 * This code is mostly position independent, so if you link the kernel at
 * 0xc0008000, you call this at __pa(0xc0008000).
 *
 * See linux/arch/arm/tools/mach-types for the complete list of machine
 * numbers for r1.
 *
 * We're trying to keep crap to a minimum; DO NOT add any machine specific
 * crap here - that's what the boot loader (or in extreme, well justified
 * circumstances, zImage) is for.
 */
        .section ".text.head", "ax"
ENTRY(stext)


 


이곳에 다음과 같이 TRACE OK 라는 문자열을 출력하는 루틴을 추가 합니다.

 

.section ".text.head", "ax"
ENTRY(stext)

// 추가 되는 소스 시작 
        adr     r0, trace1_str
        bl      printascii
        b       __error

trace1_str : .asciz  "\nTRACE OK"
         .align

 // 추가 되는 소스 끝



그리고 컴파일 한후 보드에 올려서 어떻게 출력되는지 확인 합니다.

 
 


[A015_030_kernel_debug_test_1.png]

정상적으로 표출되었죠?

후후..

일단 커널의 압축을 제대로 풀렸고 뭔가 진행은 된다는 것이 확인 되었네요..

도대체 어디서부터 멈추어 있는 것일까요?

오늘은 여기까지..

참.. 위 소스에 대한 설명은 굳이 하지 않겠습니다.

공부해 보세용.. 후후

Trackback 1 Comment 1
  1. dawnsea 2011.07.25 12:36 신고 address edit & del reply

    많은 도움이 됐습니다. 감사합니다!!

2009.06.02 21:47

2.6.28 커널로 갈아타기 - ARM 커널과 머신 아키텍쳐 번호


머신 번호 불일치 디버그 메세지

 

그래도 이 화면까지 왔다면 압축 해제는 정상적으로 진행된 겁니다.
그런데 그 다음 진행이 안되겠죠?

일단 영어를 해석해 봅시다.
아시는 분은 아시겠지만 제가 영어는 영 꽝입니다.  ㅠㅠ

표출된 내용을 콩글리쉬로 해석하면

에러: 그런 머신 ID는 지원하지 않는다.( r1 = 0x00000bb8 )

뭐 이런 겁니다.

그 다음에 지원하는 것들은 이런 이름이 있고 ID는 이런 거다.

솔찍히, 저 이 메시지 보고 무척 놀랐습니다.

이렇게 친절하게 커널이 바뀌었다니

오호호호..

옛날에는 상상도 못했던 일입니다.

여러분들은 복 받은줄 아십시오… 쩝.

Machine Type Number(머신 타입 번호)

이 Machine ID란 개념은 리눅스 커널 중에서 ARM 만 있습니다.
다른 말로 Machine Type Number 란 말을 씁니다.

하여간 리쉘 워킹( 발음이 맞는지 잘 모르겠음) 이 양반이 ARM 용 커널을 만들었으니 이 양반 마음대로 이지만 이 부분 만큼은 영 맘에 안 듭니다.  

처음 만드실 때 나름대로 고민 하셨겠지만 하여간 영 아니라는 겁니다.  

어쨌든 규칙은 규칙  

이건 부트로더가 커널을 호출할 때
R1 에 머신 타입 번호 를 넘겨 주어야 하고 커널이 넘겨진 번호를 인지 할 수 있어야 합니다.

이 머신 타입 번호는 커널이 보드를 구별하기 위한 번호인데 이 머신 ID를 얻기 위해서는  

     http://www.arm.linux.org.uk/developer/machines/

 요기로 가셔서 등록해야 합니다.

 EZ-S2410 은 다음과 같이 등록되어 있습니다.

1309   EZ-S2410(FALINUX)   ez_s2410   Hyung-Gi Jang

즉 1309 번이 이에 해당하는 ID 입니다. 

그럼 여러분이 가지신 보드로는 ID 등록을 하지 못하면 커널을 못 사용 하냐구요?
그건 아니죠..

남에 것 일단 빌려서 써도 되죠..
그냥 규칙일 뿐인걸요..

우리도 일차 목표는 시리얼 부팅이잖아요..
머신 번호와 보드 셋업을 하기 위한 정식 절차는 조금 미루어 보자구요….

자 일단 현재 커널의 불만은 내가 알고 있는 보드 ID가 없다는 거잖아요..
그렇다면 위에 나온 것 중 하나를 이용해서 처리 하면 되지 않겠습니까?

이지부트에서 Machine Type Number 설정
이지부트에서는 set 명령을 통해서 커널에 전달할 Machine Type Number를 설정할 수 있습니다.

일단 삼성에서 나온 보드 중 공식적인 보드 SMDK2410 의 ID를 이용해 보기로 하지요 

부팅 에러 메시지를 보면 이렇게 되어 있습니다.

000000c1 SMDK2410

즉 0xC1 --> 193 번 이 Machine Type Number 입니다.  

그런데 웹 페이지에 가보면  

193 smdk2410 smdk2410 Jaeoh Cha       도 있고
1703 SMDK2410 control Han Jae Lyong    라고 되어 있습니다.  

어떤게 맞을까요? 

예 일단 커널 부팅 에러 메시지에 나온 항목이 맞습니다.  

왜 이렇게 부팅에서 여러가지 ID 값들이 나오고 있을까요? 

예 가능한 모든 보드 종류를 모두 커널 소스상에 포함 시켰기 때문입니다.

그래서 최적화 시키고 싶다면  필요한 보드와 관련된 것만 커널 소스상에 포함 시키면 됩니다.
어찌되었든

부트로더에서 set 명령을 통해서 193 을 Machine Type Number로 사용합시다.

 

[A010_010_boot_loader_set_machine.png]

 13번 항목을 고치면 됩니다.
 
그리고 S 를 이용하여 저장하고 Q 로 빠져 나간후

rst 명령으로 재 부팅하여 커널 부팅을 해 봅니다. 

 

EZBOOT>rst
System Soft Reset.......
EZBOOT>0123B

WELCOME EZBOOT V2.3.04 (FALINUX Co.,Ltd) ......S3C2410(EZ-S3C2410) (266MHz)
Program by You Young-chang, Oh Jae-Kyong, Jang Hyung-Gi
Last Modify May 10 2009

  Detect Samsung NAND 64M 3.3V 8-bit Flash : vid=EC pid=76
  SIZE 64-Mbytes (page=512, block=16K)

Quickly Autoboot [ENTER] / Goto BOOT-MENU press [space bar].

Copy Kernel Image .....
Copy Ramdisk Image .....
Starting kernel [MARCH 193]...
kernel command [EZBOOT mem=64M initrd=0x30800000,5M root=/dev/ram0 ramdisk=16384 console=ttySAC2,115200    ip0=192.168.102.101 mac=00:FA:01:A2:13:04 netmask=255.255.0.0 gw=192.168.10.1 host=192.168.10.61 nandparts=2,8,54 ]
Uncompressing Linux..................................................................................................................... done, booting the kernel.
Linux version 2.6.28.10 (root@localhost.localdomain) (gcc version 3.4.3) #6 Tue May 26 10:46:55 EDT 2009
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: SMDK2410
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410A (id 0x32410002)
S3C2410: core 266.000 MHz, memory 133.000 MHz, peripheral 66.500 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: EZBOOT mem=64M initrd=0x30800000,5M root=/dev/ram0 ramdisk=16384 console=ttySAC2,115200    ip0=192.168.102.101 mac=00:FA:01:A2:13:04 netmask=255.255.0.0 gw=192.168.10.1 host=192.168.10.61 nandparts=2,8,54
irq: clearing pending status 00000400
irq: clearing subpending status 00000080
PID hash table entries: 256 (order: 8, 1024 bytes)
timer tcon=00000009, tcnt d877, tcfg 000002ff,00003333, usec 00001719
Console: colour dummy device 80x30
console [ttySAC2] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 55952KB available (3320K code, 327K data, 152K init)
Calibrating delay loop... 132.71 BogoMIPS (lpj=331776)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 484 bytes
NET: Registered protocol family 16
S3C2410 Power Management, (c) 2004 Simtec Electronics
S3C2410: Initialising architecture
S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics
DMA channel 0 at c4808000, irq 33
DMA channel 1 at c4808040, irq 34
DMA channel 2 at c4808080, irq 35
DMA channel 3 at c48080c0, irq 36
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
checking if image is initramfs...it isn't (bad gzip magic numbers); looks like an initrd
Freeing initrd memory: 5120K
NetWinder Floating Point Emulator V0.97 (extended precision)
JFFS2 version 2.2. (NAND) (SUMMARY)  짤 2001-2006 Red Hat, Inc.
msgmni has been set to 119
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach
s3c2410-lcd: probe of s3c2410-lcd failed with error -22
lp: driver loaded but no devices found
ppdev: user-space parallel port driver
Serial: 8250/16550 driver4 ports, IRQ sharing enabled
s3c2410-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
s3c2410-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
s3c2410-uart.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
brd: module loaded
loop: module loaded
dm9000 Ethernet Driver, V1.31
Uniform Multi-Platform E-IDE driver
ide-gd driver 1.18
ide-cd driver 5.00
Driver 'sd' needs updating - please use bus_type methods
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410-nand s3c2410-nand: Tacls=3, 22ns Twrph0=8 60ns, Twrph1=3 22ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 32 at 0x00080000
Bad eraseblock 655 at 0x00a3c000
Creating 8 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00004000 : "Boot Agent"
0x00000000-0x00200000 : "S3C2410 flash partition 1"
0x00400000-0x00800000 : "S3C2410 flash partition 2"
0x00800000-0x00a00000 : "S3C2410 flash partition 3"
0x00a00000-0x00e00000 : "S3C2410 flash partition 4"
0x00e00000-0x01800000 : "S3C2410 flash partition 5"
0x01800000-0x03000000 : "S3C2410 flash partition 6"
0x03000000-0x04000000 : "S3C2410 flash partition 7"
usbmon: debugfs is not available
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
usbcore: registered new interface driver libusual
usbcore: registered new interface driver usbserial
USB Serial support registered for generic
usbcore: registered new interface driver usbserial_generic
usbserial: USB Serial Driver core
USB Serial support registered for FTDI USB Serial Device
usbcore: registered new interface driver ftdi_sio
ftdi_sio: v1.4.3:USB FTDI Serial Converters Driver
USB Serial support registered for pl2303
usbcore: registered new interface driver pl2303
pl2303: Prolific PL2303 USB to serial adaptor driver
mice: PS/2 mouse device common for all mice
S3C24XX RTC, (c) 2004,2006 Simtec Electronics
s3c2410-i2c s3c2410-i2c: slave address 0x10
s3c2410-i2c s3c2410-i2c: bus frequency set to 377 KHz
s3c2410-i2c s3c2410-i2c: i2c-0: S3C I2C adapter
S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics
s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
RAMDISK: Couldn't find valid RAM disk image starting at 0.
List of all partitions:
1f00              16 mtdblock0 (driver?)
1f01            2048 mtdblock1 (driver?)
1f02            4096 mtdblock2 (driver?)
1f03            2048 mtdblock3 (driver?)
1f04            4096 mtdblock4 (driver?)
1f05           10240 mtdblock5 (driver?)
1f06           24576 mtdblock6 (driver?)
1f07           16384 mtdblock7 (driver?)
No filesystem could mount root, tried:  ext3 ext2 cramfs vfat msdos iso9660 romfs
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)



음 하하하… 

일단 커널은 떴습니다.  

자 이제 다른 보드들도 진행해야 하겠죠? 

EZ-S2410 보드 사신 분이야 상관 없지만
다른 고객분들도 아쉬워 하시잖아요?

 자 이제 이제까지 작업한 환경 설정을 다음에 보는 것과 같은 명령을 이용하여 저장하고  

[root@localhost linux]# cp .config arch/arm/configs/ezs3c2410_defconfig


 서브 버전에 커밋 합시다.

root@localhost linux]# cd arch/arm/configs/
[root@localhost configs]# svn st
?      ezs3c2410_defconfig
[root@localhost configs]# svn add ezs3c2410_defconfig
A         ezs3c2410_defconfig
[root@localhost configs]# svn ci -m "EZ-S2410 serial first portign sucess"

 


Trackback 0 Comment 0
2009.05.29 23:48

2.6.28 커널로 갈아타기 - zImage 와 시리얼 포트

EZ-S3C2410 용 이지부트 시리얼 포트

자…

이제 여러분은 눈치 채셨을 겁니다.

커널 소스상에서 압축 푸는 부분부터 시리얼 포트를 수정해야 한다는 것을

우선 부트로더부터 확인해 봅시다.

EZ-S3C2410 용 이지부트는 시리얼 포트(UART) 로 3번째 것을 사용합니다.

이지 부트 로더의 다음 소스 부분에서 처리 하고 있습니다.

소스 : ezboot\arch_s3c2410\ console.c

void console_init( u32 baudrate)
{
    int  dummy;
                                                                 
    // 포트를 선택한다.
    UART = (volatile u32 *) &(S3C2410_REG_UART2_BASE);
        :
        :

}



오호…

UART2 라서 두 번째 포트라고 우기시는 분 혹시 있으신 거 아니죠?
UART0 번부터 시작합니다. ^^

zImage 시리얼 포트 관련 함수 추적하기

그렇다면

zImage 의 head 프로그램이 압축을 풀면서 메시지를 표출할 때 사용하는 포트를 UART 2 번을 사용해야 하는 겁니다.

이걸 수정하려면 당연히 시리얼 포트를 처리하는 함수를 찾아서 이 부분을 수정해야 겠죠?

우선 ARM 에서 커널 압축 이미지를 푸는 소스의 위치는 어디 일까요?

예 바로 요기 입니다.

              linux/arch/arm/boot/compressed/

이중 head.S 가 가장 먼저 실행하는 루틴을 가지고 있고
misc.c 가 압축을 푸는 부분입니다.

이중 misc.c 를 분석하면 압축 해제 중에 다음 두 가지 루틴을 호출하게 됩니다.
뭐.. 기타 다른 매크로 함수도 있지만 가장 중요한 것을 꼽자면 이 두 가지 입니다.

              static inline void arch_decomp_setup(void)
              static inline void putc(char c);

arch_decomp_setup 함수는 압축을 해제 하기 전 초기화 할 루틴을 선언하도록 되어 있습니다. 예를 들면 시리얼 포트 초기화 같은 거죠

putc 함수는 압축을 해제 할 때 문자를 표출할 때 사용되는 가장 기본 되는 매크로 함수로 시리얼 포트로 한 글자 내 보내는 처리를 하게 됩니다.

이 두 함수가 사용되는 곳을 찾기 위해서

                 linux/arch/arm/

이 디렉토리에서

                  [root@localhost arm]# grep arch_decomp_setup * -R

명령을 실행하면 검색 결과로 너무 많은 것이 나옵니다.
 

흐흐

그래서 제가 골라 주면

      plat-s3c/include/plat/uncompress.h:arch_decomp_setup(void)

요놈이 되겠습니다.

이게 맞는지 어떻게 아냐구요?

그건 plat-s3c/include/plat/uncompress.h 에서 일부러 에러가 나도록 편집해서 커널을 컴파일 해 보면 압니다.

그리고 일단 통밥상 plat-s3c 이런 문구가 있잖습니까?

이건 플랫폼 S3C 계열이다. 뭐 이런 의미죠..

Arm 에서는 3가지 개념이 있습니다.

ARCH , MACH ,PLAT

흠…. 이건 나중에 설명하기로 하죠…

이런 거 일일이 설명 하다 보면 진도 못 나갑니다. ㅎㅎ

일단 소스를 훓어 보다 보면

초보분들



뭐가 뭔지 모르실텐데요…

다른 것은 제쳐 두고 시리얼 출력하는 부분이 어디 인가를 추적해 보면

대략 다음과 같은 매크로가 시리얼 처리를 위한 지정임을 알 수 있습니다.

     #define uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C_LOWLEVEL_UART_PORT)

즉 uart_base 가 처리되는 출력 주소를 지정하게 되는 겁니다.
 

흠.

그렇다면

여기서 핵심 키워드는

        CONFIG_S3C_LOWLEVEL_UART_PORT

같군요

호~~

       CONFIG_

이런 접두사가 붙었다면 이것은 커널 컴파일 환경 설정 변수라는 의미인데
이것을 사용자가 선택하도록 하는 부분이 어디에 있겠다는
생각이 머리에 팍~스쳐 지나갑니다.

이런 CONFIG_ 가 붙은 변수는 Kconfig 상에서 CONFIG_ 를 제거한 키워드로 찾아 봐야 합니다.

요렇게요

     [root@localhost arm]# grep S3C_LOWLEVEL_UART_PORT * -R | grep Kconfig

이렇게 찾아 보니

     arch/arm/plat-s3c/Kconfig

란 파일에

    “S3C UART to use for low-level messages” 란 메시지로


S3C_LOWLEVEL_UART_PORT 를 선언하고 있는 것을 알 수 있습니다.

Kconfig 는 커널 컴파일 옵션 설정용 파일이므로

그렇다면 우리는

    make menuconfig 란 명령을 이용해서

이 값을 재 설정해야 한다고 판단할 수 있습니다.

커널 컴파일 환경 설정

수정 순서는

System Type --> S3C UART to use for low-level messages
Kernel hacking -->  S3C UART to use for low-level debug

순 입니다.

이걸 화면으로 찍어 보면 다음과 같습니다. 

[

]

  [A009_000_kernel_config_b2_580.png]
 

[A009_000_kernel_config_b3_580.png]
 

 [A009_000_kernel_config_b4_580.png]
  

[A009_001_kernel_config_1_580.png]
  

[A009_002_kernel_config_2_580.png]
  

[A009_003_kernel_config_3_580.png]
  

[A009_004_kernel_config_4_580.png]
  

[A009_005_kernel_config_5_580.png]
  

[A009_006_kernel_config_6_580.png]


자 이제 설정이 끝났으면 컴파일 해서 보드에 올려 봅시다.

[root@localhost linux]# make zImage
  :
  :
[root@localhost linux]# cp arch/arm/boot/zImage /tftpboot/zImage.ez-s3c2410
cp: overwrite `/tftpboot/zImage.ez-s3c2410'? y




짜짠~~~

이런 메시지가 나옵니다.

 
[A009_010_kernel_boot1_580.png]

일단 무언가 나오기는 하는데

요건 도대체 무슨 화면일까요?


Trackback 0 Comment 1
  1. Cheap Uggs 2011.10.11 16:48 신고 address edit & del reply

    Fashion business attracts a large number of young people these days don't just for the reason that this is a alternatively new occupation, but also it can be supposed to comprehend person's likes while in the subject of fashion. In addition to, it's always particularly a high-paid career now. Any time a youthful individual decides to link his / her activity when using the trend community very little comes to head except a single its element - vogue design and style. Probably, handful of customers actually understand that it is a separate discipline of trend sector. In reality, you can find an ideal variety of other professions and specialties in including planning garments, style and design, online marketing, merchandising, and many others.

2009.05.26 21:38

2.6.28 커널로 갈아타기 - arm 커널 부팅과 시리얼 포트


광고

커널 컴파일 했습니다. 커널 올렸습니다. 그런데 동작하지 않습니다.
막약에… 커널 올리고 부팅했는데 그냥 시리얼 메시지 나오면 아무 문제가 없죠..
하지만 이렇게 어떤 문제가 터지면 어디서 문제가 발생했고 어디를 고쳐야 하는지 알아야 하죠?

음하하하! 저희는 알죠 

물론 여러분들도 알 수 있습니다. 커널 소스를 분석하고 학습하면요…
대신 시간이 걸립니다.
그 시간을 아끼시고 싶으십니까? 저희에게 맡겨 주십시오.

광고 였습니다.
쩝…
이 먹고사니즘이여…

처자식 때문에 뻔뻔하게 회사 광고 합니다. ( 흑흑 ) 

그런데

저희 회사가 어떤 회사 입니까? 

자료와 기술은 공유하자라는 아주 착한 마인드를 가진 회사 아니겠습니까? 

그래서 이렇게 보드를 사시고 학습하고자 하는 의욕이 계신 분들에게 그 비법을
일부 공개하는 것 아니겠습니까? 

자. 이제 비법을 공개해 봅시다. 

ARM 용 zImage

 EZ-S3C2410은 ARM 이죠  

그래서 이후에 이야기 하는 것은 S3C2410만 해당되는 것이 아니고 ARM에 모두 해당 되는 겁니다.  

ARM용 커널은 특별한 경우가 아니라면 zImage 형태로 만들어 집니다.  

이 커널 이미지는 압축된 이미지죠.. 

엥? 

커널 이미지가 압축되어 있다?
그러면 어떻게 실행 되죠?

예… 맞습니다.

압축된 상태에서는 실행되지 않습니다.  

 우선 아래 그림을 봅시다.

 

그림을 보시면 아시겠지만

동작되는 진짜 커널 바이너리 이미지는 vmlinux 라고 이름이 붙습니다. 

근데 요놈 사이즈가 좀 큽니다.
임베디드 시스템은 아무래도 저장 공간의 부족에 시달리죠..
물론 최근에 들어와서는 안 그렇습니다만 

어쨌든 용량을 조금이라도 줄이려고
이걸 gzip 압축 프로그램을 이용하여 piggy.gz 파일로 만듭니다.  

자 이 압축된 것이 나중에 보드에 올라 갔을 때 압축이 해제 되어야 하지 않겠습니까?
또 압축이 해제된 커널이 실행도 되어야 하지 않겠습니까?  

이렇게 압축도 해제하고 실행도 시키는 프로그램을 head 라고 하는데 이것과 압축된 커널 이미지 piggy.gz 합쳐서 zImage 라고 이름 짓습니다.  

처음 실행하고 압축 이미지를 풀고,
풀린 커널로 점프하도록 하는 것은 head.S 가 담당합니다.  

압축을 해제 하는 실제 동작은 misc.c 에서 합니다.
이 부분에 대한 자세한 구조를 굳이 여기서는 말하지 않겠습니다.

귀찮잖아요 쩝~ 

그런데 말이죠..
만약 여러분이 사용하는 부트로더가 압축을 푸는 루틴을 가지고 있으면 piggy.gz 만 사용해서 부팅할 수 있습니다. 

그런데 굳이 그래야 할 이유가 있을까요?  이미 커널에서 지원하는데
또 만들면 귀찮잖아요…

그쵸? 

 zImage 와 콘솔용 또는 메시지 표출용 시리얼 포트

자 어쨌든 zImage 가 동작하면서 압축을 풀겠죠? 

그런데

zImage 가 수행되면서 “나 압축 푸는 중이야” 하는 것을 사용자에게 알려주어야
사용자가 답답해 하지 않겠죠? 

그래서 압축을 해제 하면서 메시지를 표출 하는데
임베디드 시스템에서는 메시지 표출 방법으로 주로 시리얼 포트를 이용하죠

당연히 zImage 의 실행 소스 부분에 이 시리얼 포트를 사용하는 부분이 있죠

그렇다면 아무런 메시지가 나오지 않았다는 것은
이 시리얼 포트로 데이터를 전송하는 부분이 문제가 있는 것이겠죠? 

물론 다른 이유도 있겠지만  

우선 이 부분부터 의심해 봅시다.  

왜냐하면 

이지보드는 다른 회사의 평가 보드와 다르게 콘솔용 시리얼 포트로 사용되는 포트가첫번째 것이 아니기 때문입니다.

판매되는 평가 보드들에 동작되는 부트로더와 커널은  메시지를 표출하기 위해서 MCU 의 첫번째 시리얼 포트를 콘솔용 시리얼로 사용하도록 설정되어 있습니다.  

그에 반해 저희 이지보드는 보통 세번째 것을 이용합니다.  

왜냐하면  

커널 콘솔용 시리얼 포트로 사용되거나 부트로더 진행 표시 및 입출력용으로 사용되면 다른 목적으로 사용이 곤란해 집니다.  

그래서 저희는 가장 나쁜 성능을 가지는 포트나 가장 사용이 안될 가능성이 높은 것으로 시리얼 포트를 선택한 겁니다.  

주로 세번째 시리얼 포트들이 가장 나쁜 성능을 가지고 있기 때문입니다 . 

처리 속도가 낮거나 적외선 시리얼 포트용으로 사용되는 경우도 많습니다. 

이런 차이로 인해서

기존의 유부트나 커널 환경 설정의 기본 조건이 되지 않아서 처음 커널 메시지를 보지 못하는 수가 있습니다.

그래서 가장 먼저 이 부분을 의심하는 겁니다. 

부팅 과정과 시리얼 포트



이쯤에서 리눅스가 정상적으로 부팅 되면서 거치는 프로그램의 종류와 시리얼 포트에 대하여 그림으로 알아 봅시다.

 


[A008_002_booting.png]

허허~~

의외로 응용 프로그램까지 오는 동안 많은 과정을 거치죠?  

이 그림을 글로 정리하면 다음과 같습니다.  

1) 보드가 부팅된 후 동작하는 이지부트에서  시리얼을 초기화 합니다.
2) 이후로 프로그램상에서는 printf 라는 함수를 이용하여 출력 할 수 있습니다.
3) 이때 사용되는 시리얼 포트는 3번째 것 입니다.
4) 이지부트가 zImage를 메모리에 올린 후 실행시킵니다.
5) zImage 의 head 프로그램이 실행되면 arch_decomp_setup 이라는 시리얼 초기화를 위해서 매크로 함수를 호출합니다.
6) 이후 압축 해제 진행 과정을 표시하기 위해서 putc 라는 매크로 함수를 호출 합니다.
7) 커널이 동작되면 커널의 상태를 표출하기 위해서 이지부트에서 전달된 커널 커맨드중 console= 으로 설정된 디바이스 드라이버를 이용하여 커널 메시지를 표출합니다.
8) 커널 부팅 프로세스가 모두 끝난후 init 프로세서에서는 시리얼 터미널 프로그램을 동작 시켜 login 상태로 대기 합니다.
9) Login 프로그램으로 사용되는 것이 getty 라는 프로그램인데 이때 시리얼 디바이스를 지정합니다.
10) 정상적인 부팅 과정이 끝난 후 응용프로그램이 동작합니다.
11) 만약 응용 프로그램이 시리얼 포트를 사용한다면 /dev/ttyS… 를 이용합니다.

 여러분은 이제 깨닫는 것이 있으실 겁니다.

 즉 부팅까지 여러 프로그램이 동작되어 가는데 각 진행 프로그램마다 사용되는 시리얼 포트가 달라질 수 있다는 것을..

그래서 이 부분을 하나로 통일 하는 과정이 필요한 겁니다.

 

Trackback 0 Comment 0
2009.05.18 10:35

2.6.28 커널로 갈아타기 - 커널 최초 컴파일 시험

● 커널 최초 컴파일 시험

커널을 포팅하기 전에 가장 먼저 커널 컴파일 옵션을 설정해 보고 한번 컴파일을 해 보아야 합니다. 
이런 과정을 거치는 이유는 개발 환경을 검증하기 위한 목적이 가장 강합니다.

그런데 커널 컴파일 옵션을 생짜로 모두 설정하러 다니는 것이 그리 좋은 것이 아니죠..

가장 좋은 것은 누군가가 해 놓은 환경 설정을 내 환경에 맞추는 것이 좋아요..

 자 1 차 목표는 EZ-S3C2440 이었죠…

 그런데 ..

 리눅스 커널 소스에서 암 용 커널 환경 설정들이 있는 곳이 여기입니다.

linux/arch/arm/configs/

이중에 이런 파일이 있네요…

s3c2410_defconfig

흐흐흐…

그래서 작전을 변경했습니다.

 자 1 차 목표를 EZ-S3C2410으로 하기로

흐흐흐 

앗 약속이 틀리다구요?

하하하..

제 맘입니다.

거저 먹을 수 있는 찬스를 전 놓치기 싫지요.. 

자 이제 시작해 봅시당


● 환경 설정 및 커널 컴파일


이미 작업해 놓은 커널 컴파일 옵션을 적용하는 것이 그리 어려운 것이 아닙니다.

적용전에 우선 Makefile을 약간 손보아야 합니다.

커널소스

linux\Makefile 에서 193 라인 쯤에

크로스 컴파일을 위한 처리 부분이 있습니다.

193 ARCH            ?= $(SUBARCH)
194 CROSS_COMPILE   ?=

이 부분을 arm 용 크로스 컴파일이 될 수 있도록 다음과 같이 고칩니다.

193 ARCH            ?= arm
194 CROSS_COMPILE   ?= arm-linux-


193 라인의 ARCH 는 실제로 리눅스 소스상에 어떤 아키텍쳐 소스를 참조할 것인지등과 같은 컴파일 과정에 영향을 미칩니다.

 예로 보면 linux/arch 하부 디렉토리에는 arm 이라는 디렉토리가 있습니다. 이를 지정하기 위한 경우가 그 한 예죠.

194 라인은 gcc 컴파일의 앞부분에 붙은 접두사입니다.

원래 i386 네이티브 컴파일러라면 앞에 특별히 접두사가 붙지 않습니다.
하지만 arm 이라면 다르죠
이건 어떤 크로스 컴파일러를 설치했고 해당 크로스 컴파일러의 접두사가 어떤 형태인가에 달라지는 겁니다.
저희 회사에서 제공하는 arm 크로스 컴파일러라면 앞에 arm-linux- 가 붙습니다. 

만약 EZ-AU1250 모델과 같은 mips 용 크로스 컴파일러라면 앞에 mipsel-linux- 같은 형태로 붙게 됩니다. 

어쨌든 이렇게 수정한 후 다음과 같은 명령을 사용해서 소스를 청소해 줍니다. 

[root@localhost linux]# make mrproper
  [root@localhost linux]# make distclean


mrproper
 
는 이전에 설정한 정보를 지우거나 새로운 커널 소스를 가져다 컴파일 할 때에 사용합니다. 이전 커널을 컴파일할 때 만들어진 오브젝트 파일(*.o)과 의존성 설정, 컴파일 환경 설정값, 버전 정보 등 새로 시작하는 컴파일에 영향을 주는 이전 정보들을 삭제합니다.

이전에 설정된 컴파일환경을 재사용한다면 이 명령을 수행할 필요는 없습니다.

distclean은 리눅스 커널소스인 .tar.gz 를 풀었을 때와 같은 상태로 만들어 주는 겁니다.

어찌 되었든 이 두 과정을 거쳐서 소스를 깨끗한 상태로 만든 후 다음 명령을 쳐서
S3C2410 컴파일 옵션 설정 상태로 만들어 버립니다.

[root@localhost linux]# make s3c2410_defconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/docproc
  HOSTCC  scripts/basic/hash
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/kxgettext.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/lex.zconf.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
#
# configuration written to .config
#
[root@localhost linux]#



자 이제 어떻게 설정되어 있나 잠깐 들여다 봅시다.

make menuconfig 명령을 쳐서 커널 환경 설정 작업 상태로 들어 갑니다.

[root@localhost linux]# make menuconfig

 


여기서 System Type 을 선택합니다.


 
시스템 타입 설정에 S3C2410 이 보이죠? 일단은 제대로 환경 설정이 된거죠..

 이제 컴파일 해 봅시다.

컴파일은 arm 의 경우라면 make zImage 입니다.

[root@localhost linux]# make zImage
     :
  SYSMAP  .tmp_System.map
  OBJCOPY arch/arm/boot/Image
  Kernel: arch/arm/boot/Image is ready
  AS      arch/arm/boot/compressed/head.o
  GZIP    arch/arm/boot/compressed/piggy.gz
  AS      arch/arm/boot/compressed/piggy.o
  CC      arch/arm/boot/compressed/misc.o
  LD      arch/arm/boot/compressed/vmlinux
  OBJCOPY arch/arm/boot/zImage
  Kernel: arch/arm/boot/zImage is ready
[root@localhost linux]#



위와 같은 메시지가 나오면 정상적으로 컴파일이 끝난 겁니다.

생성된 커널 이미지arch/arm/boot/zImage 파일이 되겠습니다.

이렇게 해서 생성된 이미지를 부트로더를 이용해서 보드에 올리면 되는데

문제는!

이것이 제대로 동작할 것이라고 믿을 수는 없다는 겁니다..
재수 좋으면 동작 할 것이고
재수 없으면 동작 안 할겁니다.

복불복이라고나 할까?

여러분의 보드가 배신할지 모르기 때문입니다.

Trackback 0 Comment 3
  1. seso 2010.03.05 03:02 신고 address edit & del reply

    흠 falinux forum 에서 퍼온글이네요. 퍼온글이면 출처정도는 밝혀야 하지 않을까요 작성한분이 힘들게 작성한 글인데

    • 유영창 2010.03.09 22:35 신고 address edit & del

      저글 제가 쓴건데요 ^^

  2. Cheap Uggs 2011.10.11 16:24 신고 address edit & del reply

    Fashion business attracts a large number of young people these days don't just for the reason that this is a alternatively new occupation, but also it can be supposed to comprehend person's likes while in the subject of fashion. In addition to, it's always particularly a high-paid career now. Any time a youthful individual decides to link his / her activity when using the trend community very little comes to head except a single its element - vogue design and style. Probably, handful of customers actually understand that it is a separate discipline of trend sector. In reality, you can find an ideal variety of other professions and specialties in including planning garments, style and design, online marketing, merchandising, and many others.

2009.05.10 13:55

2.6.28 커널로 갈아타기 - 개발 환경

들어가며

저돌적인 학습 욕구가 왕성한 초보자 분들이 가장 먼저 무한 삽질의 세계에 빠져 들면서 혼란스러워 하는 것이 바로 개발 환경 구축이죠..

윈도우 프로그램의 개발 환경은 솔찍하게 그냥 간단합니다.

상용 패키지 하나 깔면 끝~~~ ( 뭐 어둠의 경로를 애용하시는 분들이 더 많다는 소문도 있지만 쩝~ )

임베디드 컨트롤러 특히 8비트 프로세서들의 개발 환경도 조금 복잡하지만 에뮬레이터 한 개와 상용 패키지 하나 깔면 끝~~

근데…

이놈의 임베디드 리눅스 하려면 ( 물론 돈 안 들이려고 하는 조건일 때 )

뭐가 이리 복잡하고 할 수 있는 다양한 방법이 존재 하는지

그래서 처음부터 좌절하는 경향이 있죠..

그래서 이번 진행 과정에 사용되는 환경에 대하여 제가 사용하고 있는 환경을 공개하겠습니다

 

개발 환경

커널을 포팅하는 과정은 다음과 같은 행위의 반복입니다.

1) 커널을 수정한다.
2) 커널을 컴파일 한다.
3) 커널을 보드에 올린다.
4) 보드를 리부팅한다.
5) 커널이 부팅된 후 진행 상태를 커널 메시지로 관찰한다.
6) 버그나 다음 작업 진행을 위해서 1) 부터 다시 시작한다.

자 이런 행위를 하기 위해서 필요한 것들이 무엇일까요?  

우선 개발용 컴퓨터와 커널이 포팅되는 타켓이 필요하겠죠? 

그 외에 파워써플라이와 오실로스코프가 있으면 좋겠지만 사실 하드웨어가 이상이 없다면 굳이 필요 없습니다. 파워 써플라이는 아답터로 대신 할테고 하드웨어 상태가 오실로스코프를 쓸 정도면 초보자들은 일단 손을 띄시는 것이 정신 건강에 이롭습니다.  

이제 개발용 컴퓨터와 타켓은 서로 연결되어야 합니다.

뭘로 연결될까요?
예 그렇습니다.
시리얼 케이블과 이더넷 네트워크 케이블입니다. 

네트워크 구성은 아무래도 컴퓨터와 보드를 직접 연결하기 보다는 네트워크 허브나 공유기를 이용하시면 더 편하지요.. 

전 당연히 허브를 이용한 구성으로 작업 하고 있습니다.

제 시스템 환경 구성은 다음 그림과 같습니다.

 

 

자 이제 하드웨어 와 시스템 구성은 되었습니다.  

그 다음 하는 것은 ?

1) 커널을 수정한다.

그렇습니다.

커널을 수정해야 합니다.  

커널은 컴퓨터에서 수정해야 하는데 해당 컴퓨터는 운영체제가 있어야 겠죠… 

저는 개발 환경 운영체제가 윈도우 XP 를 사용합니다.  

허허~~

많은 분들이 제가 열혈 리눅서라고 착각하시는 분들이 있고 제가 리눅스 운영체제에서 모든 작업을 할 것이라고 상상하시는 분들이 있을지 모르지만  

전 VI 에디터도 잘 못 씁니다. 물론 사용할 수야 있지만 저희 회사에 근무하고 계시는 켈프 짱이신 박진호씨의 화려한 VI 사용 실력을 보면 전 그냥 쭈구러 듭니다.

 리눅스 명령어도 사실 몇 개 밖에 모릅니다.  

하하 

그래도 임베디드 리눅스와 관련된 기술만은 타의 추종을 불허 한다고 자신..
( 퍽~~~ ㅠㅠ 죄송합니다. 잠시 오버 했습니다. ) 

어쩄든 윈도우에서 편집기 돌려 리눅스 커널 소스를 수정합니다.  

오호 … 그런데  혹시 아십니까? 

리눅스 커널소스를 윈도우에서 압출을 풀면 쪼까 문제가 된다는 것을?

리눅스 커널 소스는 원칙적으로 리눅스 파일 시스템을 이용한다는 가정하에 구성되고 있습니다.  

가장 대표적인 것이 심볼릭 링크 입니다.
또 한가지는 소스 파일 중 어셈블러 파일일 경우 확장자가 대문자인경우와 소문자인 경우가 약간 차이가 납니다.  

어찌 되었던

리눅스 커널 소스는 리눅스 파일 시스템에서 압축을 풀고 작업을 해야 합니다.  (반드시는 아닙니다.)

자 ..

그렇다면 아무래도 리눅스 시스템이 필요하겠죠? 

그런데 눈치 채셨겠지만 개발 시스템 구성상 전 이미 운영체제를 XP 로 설치한 상태이고 리눅스는 멀티 부팅하기 귀찮아 합니다.  

그래서 저는 coLinux를 사용합니다.

 이거 저에게는 노트북에도 설치해서리 현장에 갈 경우 씁니다.
아니면 다른 실험실 같은 곳에서 개발 작업이나 연구를 해야 할 때 씁니다.  

한마디로 죽이는 놈이 coLinux 입니다.  

coLinux 설치방법은 저희 회사 포럼에 잘 나와 있죠. 바로 여기

http://forum.falinux.com/zbxe/?mid=coLinux


이 강좌에 글을 따라 하실 때 먼저 브릿지 모드로 네트워크를 설정하는 강좌를 먼저읽고 진행하기를 권장합니다.

http://forum.falinux.com/zbxe/?document_srl=507011

솔직히 제 경험상 가장 실패 율이 적습니다.

그런데 위 강좌 글을 따라 하면 2 % 부족함을 느낄 겁니다.

 예 ..

그렇습니다.

 진행을 하다 보면 이것저것 필요한 개발 패키지와 시스템이 설치 되어 있어야 합니다.

 이걸 또 일일이 찾아 다니며 필요한 것들이 무엇인가 찾고 하는 것도 그리 쉬운 것이 아니죠…

그래서 제가 여러분들에게 선물을 하나 하기로 했습니다 .

그게 뭐냐?

제가 사용하고 있는 coLinux 이미지를 공개 하기로 한 것이죠

  공개 coLinux 이미지 내용 

 이 이미지는 다음과 같은 환경 조건을 가지고 있습니다.

 

파일 시스템 크기 :  6G
배포판 기반  : 페도라 9 ( 가장 최신것으로 업데이트 된 상태임 )
네트워크  : 100.100.100.100 
넷마스크  : 255.255.0.0

설치된 크로스 컴파일러 :

arm 용 3.4.3
mips 용 3.4.3
mingw 윈도우용 컴파일러

네트워크 서버 :

tftp 서버    /tftpboot/  디렉토리 서비스
nfs 서버   /nfs/ 디렉토리 서비스
삼바서버   /project/ 디렉토리 서비스

각종 리눅스 개발 툴에 필요한 패키지 대부분 설치
man 페이지 : 한글 맨페이지 및 영문 맨페이지

사용자 명은 : user
암호   : user

Root 암호는 : root

 이거 어디서 받냐고요? 여기서 받습니다.

http://ftp.falinux.com/colinux/fedora9/Fedora9-6G-2009-05-05-yyc.img

이 이미지는 우선 포럼에서

http://forum.falinux.com/zbxe/?document_srl=505577 글을 보고

colinux 설치 하신 후

제가 올린 위 이미지로 살포시 바꾸시기 바랍니다.

이 이미지에 보면 내부에 /root 에 스크립트 파일이 하나 있습니다.
이건 ip와 라우터를 쉘 스크립트로 바꾸는 예제인데 혹시나 해서 하나 만들어 넣었습니다.

필요하시면 참조 하세요..
 

자 이제 제가 올려 드린 colinux 환경이라고 하면 

윈도우에서 삼바로 접근해야 할겁니다.  

네트워크 설정이

윈도우는 100.100.100.101 이고 colinux 페도라 배포판이 100.100.100.100이라면 

윈도우 탐색기에서 \\100.100.100.100\ 이렇게 하시면

Colinux 페도라의 project 에 접근 하실 수 있겠죠… 

이 네트워크 디렉토리를 이용해서 윈도우에서 편집 할 수 있을 겁니다.

 그렇지만 아직 우리는 문제가 있죠?

coLinux 에 접근 할 수 있는 방법을 알려 드려야 하는데

텔넷으로 접근해야 겟죠?

 전 tocken plus 라는 프로그램을 사용합니다 .
여기에 가시면 됩니다.

http://www.bomul.com/pds/view.html?id=53252

한국 분들이 만든 건데 미국에 회사를 차렸나 봐요..

http://choung.net/

하지만 장길석씨는 공개된 프로그램을 이용하라고 하네요
이것도 공짜거든요…

여기에 해당 글 있습니다.

http://forum.falinux.com/zbxe/?mid=manual_booting_win_tutty

시리얼 포트를 연결해서 부팅 메시지 보는 법이나

텔넷을 이용해서 리눅스 컴파일 서버에 접속하는 법은

EZ 보드 통합 매뉴얼을 참고 해 주시기 바랍니다.

기타 진행 사항은 다음 강좌에서 설명할 겁니다

Trackback 1 Comment 0
2009.05.07 08:23

2.6.28 커널로 갈아타기 - 첫번째 목표

커널 포팅의 첫번째 목표 


간단한 보드에 대한 모든 디바이스를 한꺼번에 처음부터 포팅해 나가면 그것도 엄청 많은 무한 삽질을 해야 합니다.

그래서

가장 처음 세우는 커널 포팅의 목표는

시리얼 장치로 커널 메시지가 쭈욱 나오도록 하는 것

이죠..

엥?

간단해 보인다고요?

음하하하하…


다들 그렇게 만만하게 보죠…

그런데…

막상 해 보시면…

부트로더에서 커널로 이동한 후

아무 메세지 안 나오면 좌절 합니다.

그리고 그것만큼 막대한 좌절 모드 없습니다.

해 보세요..

다행히 한번에 되면 행운아 시고요..

안 그러면 좌절 할 겁니다.

어쨋든

제가 정하는 첫 번째 목표는

시리얼 포트로 커널 부팅 메시지를 나오도록 하게 하는 거지요..

이번 글은 낚시성 글이 강하군요...

잠시 쉬어가는 페이지 였습니다.

다음 글이 분량이 좀 되기 땜시

쉬어 가라고..

아하하하하...

(휘리리릭~~~)


Trackback 3 Comment 0
2009.05.06 01:10

2.6.28 커널로 갈아타기 - 커널 포팅이란?

● 들어 가면서

포럼에 예고편까지 올린
아주 아주 요란스러운 광고에 걸 맞는
작업 진행 속도를 보이고 그에 따른 글을 정리해 올려야 하는데

공사 다망한 사건 사고가 있는, 원래 생각보다 바쁜 나날이 지나고,
그렇지만 돈 버는 것과는 썩 관련이 없는 하루 하루를 지내다 보니
글 하나 올리지 못한 남사스러운 상태가 되고 말았네요

그래도 꿋꿋하게 한 가지씩 진행해 보죠.

참! 저 따라 했을 때 질문 댓글은 허용하지만 저의 답변은 가급적 기대하지 마세요.

제 원칙 중 하나가 질문에 답변 잘 안 하기 입니다.
뭐 솔찍하게 말하면 답변했다가 실력이 뽀록 날까 봐 그렇습니다. 이해해 주세요

● 커널 포팅이란?

임베디드 리눅스를 처음 하시는 분들을 가끔 만나서 이야기 하다 보면

“나 진짜 아무것도 모르는 초짜예요”

라고 하는 눈빛을 하고 초롱 초롱한 눈망울로 저를 바라보시면서

“커널 포팅이 뭐예요?”

라고 물어 보시는 분들이 있습니다.

이때 저는 아주 친절하게 최대한 이해할 수 있도록 설명하기 위해서 이렇게 이야기 합니다.

“ 임베디드 시스템에 사용되는 컨트롤러 보드에 리눅스 커널을 올리기 위해서 제어 시스템에 맞도록 리눅스 커널의 아키텍쳐 부분 소스와 각 종 하드웨어 제어를 위한 디바이스 드라이버 소스를 어드레스 및 인터럽트 부분 등을 수정하고 초기 부팅 부분을 부트로더와 맞추어 가는 과정입니다.”

물론 이 말을 하는 순간 저는 초보 분들이 잘 이해했을 것이라는 기대를 갖고서 말이죠.

하지만 그 분들의 표정을 보면 절망합니다.

그 분들은 초보 분들이거든요..

임베디드? 컨트롤러? 아키텍쳐? 디바이스 드라이버? 부트로더?

제 설명은 좀 더 이해 못할 단어들의 나열인 거죠..

옛날 제가 처음 임베디드 리눅스 처음 시작 했을 때 처럼요.

이런 절망적인 상황에 그 초보 분들보다 약간 좀 일찍 하신 분들이 이렇게 이야기 하여 저를 구제해 주십니다.

“그러니깐요.. 유영창씨가 말한 것을 쉽게 이야기 하면요”
“보드에 리눅스가 동작하도록 하는 작업을 커널 포팅이라고 하는 거예요”

그 순간 그 초짜 분들은 정말 알겠다는 눈빛을 반짝입니다.
“그런거 군요”..

저 절망 합니다.

● 커널 포팅의 수준

그.렇.죠.

다른 장황한 설명은 굳이 필요 없는 겁니다.

자기가 원하는 리눅스 커널이 보드에서 동작하도록 하는 모든 작업이 커널 포팅인 거죠.

그런데 이런 커널 포팅에도 난이도가 있는 겁니다. 가장 난이도가 낮은 것에서 높은 순으로 보자면 다음과 같은 순서가 될 것 같네요

    ▶ 보드 포팅
    ▶  MPU 포팅
    ▶  프로세서 코어 포팅
    ▶  새로운 프로세서 추가 형태의 포팅

저..
혹시..
나중을 위해서 말하는 건데요..
리누즈 아저씨가 구분한 것은 아니고요

제 나름대로 구분한 거니까.

자신의 생각과 다르다고 딴지 걸지 마세요…

● 보드 포팅

이번에 포럼에 올리겠다고 하고 진행하고 있는 2.6.28 커널을 저희 회사 보드에 포팅 하는 것이 가장 낮은 난이도를 갖는다는 보드 포팅입니다.

왜 냐하면 2.6.28 커널은 현존하는 대부분의 임베디드용 프로세서에서 동작 하도록  수정된 상태이고 상용화된 보드들은 표준적인 보드의 하드웨어 설계 부분에서 몇 가지 부분만 살짝 고쳐 놓거나 추가 한 정도거든요.  이 정도는 커널 소스를 수정하고 적용하는 것이 크게 어려운 부분은 아니죠.

아..

그렇다고 쉽다고 오해하시면 안됩니다.

저희 회사가 먹고 사는 데는 다 이유가 있습니다.

그냥 똑같이 만들거나 추가된 부분이 없다면 그냥 쓰면 되지만 하나라도 틀리거나 하드웨어적인 트러블이 있거나 하면 리눅스 커널 특히 디바이스 드라이버나 아키텍쳐에 대한 이해가 없는 상태에서는 손 쓸 방법이 별로 없다는 거지요.

저희 회사가 그동안 10년 가까이 임베디드 리눅스만 다루고 그 과정에서 얻어진 리눅스 커널에 대한 이해와 경험이 평범한 것은 아니라는 겁니다.

흠흠….

힘들면 저희에게 맡겨 주십시오.
시간을 절약할 수 있을 겁니다.

흠흠.. 광고 였습니다. ( 이 구차한 먹고사니즘이여~~ )

● MPU 포팅

그럼 이 보다 조금 더 어려운 단계는 무엇일까요?

그건 프로세서 코어의 핵심은 같은데 기존에 없던 MPU를 커널에 추가 하는 것입니다.

예를 들면 예전에 삼성 S3C2410 프로세서가 이미 커널에 있는데 S3C2440 을 새로 개발했을 때 리눅스 커널에 이를 추가 하는 것이죠

이때는 단순한 보드 포팅이 아니죠

ARM 프로세서 계열이라면 머신 아키텍쳐 라고 하는 부분을 추가 하는 작업입니다.

이 작업은 새로운 주변 장치들을 기존 프로세서 코어와 연관하여 추가 하기 때문에생각보다 많은 작업이 필요한데 이건 주로 프로세서를 만드는 회사에서 자체적으로 하거나 저희 같은 회사에 발주를 주는 일이죠

근데 왜 우리에게 그런 일들을 안 줄까요?  전문인데 말이죠..
삼성전자가 저희를 싫어 하나 봅니다.  아하하하….

일반 회사에서는 이런 일들이 발생하지 않겠죠.

기존 리눅스 커널이 지원하지 않는 특별한 MPU를 임베디드 리눅스에 써야 할 경우인데

MPU 포팅 이거 의외로 시간 많이 걸리고 저희 같은 회사에 외주 주려고 해도 돈 많이 주어야 합니다.

그래서 일반 회사가 MPU 포팅을 하고 싶다는 문의를 하시면 저희는 그냥 리눅스 커널이 지원하는 MPU 사용하라고 권장 합니다.

그게 일반 개발자들이 만수 무강하는 지름길이죠..

그래도 부득히 하신다면야 저희는  감사 하죠 돈 주신다는데 하하하…

● 프로세서 코어 포팅

그 다음 난이도가 높은 것은 새로운 프로세서 코어 를 포팅하는 겁니다.

프로세서 코어 포팅을 하려면 커널 내부의 핵심 부분이 스케쥴러 , 가상 메모리 시스템, 인터럽트 처리 , 기존 아키텍쳐 커널 소스 부분 등을 이해 해야 하고
프로세서의 캐쉬 시스템이나 MMU 와 같은 것과 같은 부분에 대한 이해도가 높아야합니다.

사실 위에 이야기 한 커널 내부의 가장 어렵다는 메모리 관리 부분과 인터럽트 부분 캐쉬 컨트롤 등등 쉽지 않죠…

어쨌든 이런 부분의 포팅은 아주 특별한 경우가 아니면 다룰 일이 거의 없을 겁니다.

ARM 사에서 저희 회사에 외주 주려고 마음 먹을 경우라면 모를까 …

하하… 있을리가 없지요

아니면 듀얼 코어와 같은 SOC를 다루어야 하는데 외국에서 요구하는 비용이 너무 비싸서 한국에서 찾아 본다면 모를까..

그냥 있다고만 하지요..

● 새로운 프로세서 추가 형태의 포팅

역쉬 가장 난이도가 최고라면 기존에 없는 프로세서 아키텍쳐를 추가 하는 경우죠..

예를 들어 여러분이 아예 새로운 ARM,MIPS,IA32,POWERPC,AVR 과 같은 새로운 프로세서 아키텍쳐를 디자인하고 이를 리눅스에 적용시켜야 겠다고 하는 경우죠.

이런 형태의 포팅이 가장 어려운 이유는
다른 프로세서를 참조하면야 되겠지만 전체적인 구상과 설계 기준을 모두 정해야 하기 때문이죠..

아시는지 모르겠지만 리눅스 커널은 사실 리더가 따로 없습니다.
새로운 신천지를 개척할 때는 가장 처음 디자인 해 가는 사람이 모든 것을 정합니다.

그래서 어렵습니다.

잘못되었다고 알려주거나 참조 할만한 것이 없으니깐요..

그래서 가장 어렵습니다.


Trackback 2 Comment 0