멈춘 이유가 뭘까요?

S3C2410 과 S3C2440을 하면서 알려 드렸지만

대부분의 원인은 크게 세가지 입니다.

  • 머신 ID 오류
  • 잘못된 콘솔 지정
  • 인터럽트 또는 디바이스 드라이버 초기 처리시 멈춤 루틴에 의한 경우

첫 번째의 경우인 머신 ID 의 오류는 디버그 메시지 표출처리를 하면 표시 되기 때문에 바로 알수 있습니다.

 

현재 우리가 진행했던 과정을 되 짚어 보면 이 부분은 정상적으로 처리되고 있다고 판단됩니다.

 

두 번째와 세번째는 일일히 확인해야 합니다. 

 

이 두 가지의 원인을 파악하고 싶다면 우선적으로 콘솔 디바이스가 초기화 되기 직전까지 진행되는지를 확인 해 볼 필요가 있습니다.

 

이 부분은 start_kernel() 함수처리 부분 중에 console_init(); 함수를 호출하기 직전까지 정상적으로 호출되는가를 확인해 보는 것이 좋습니다.

 

이전 강좌에서 사용했던 디버그 매크로를 사용해서 확인해 보기로 하겠습니다.

 

다음 위치에 디버그 매크로를 끼워 넣습니다.

 

[init/main.c]

622         /*
623          * HACK ALERT! This is early. We're enabling the console before
624          * we've done PCI setups etc, and console_init() must be aware of
625          * this. But we do want output early, in case something goes wrong.
626          */
627
628         TRACE_LINE
629
630         console_init();
631         if (panic_later)
632                 panic(panic_later, panic_param);


커널을 컴파일 하고 보드에 올려서 이 부분까지 통과 하는지를 봅니다.

 

>>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
>>TRACE init/main.c:start_kernel:628


이 이야기는 콘솔 지정에 문제가 있다는 것을 확인해 줍니다.

 

즉 console_init() 직전까지 동작했는데 이후부터 동작하지 않는다는 것이죠..

 

이런 경우라면 두 가지를 추측할 수 있죠

 

콘솔 디바이스 드라이버 이름이 틀렸거나
콘솔 디바이스 드라이버가 제대로 동작하지 않는 경우죠..

 커널 커맨드 문자열 확인

우선적으로 전달된 커널 커맨드가 어떻게 되어 있는가를 확인해 봅시다. 부트로더에서 전달된 내용과 커널에서 받아 들이는 내용이 일치해야 하겠죠?

 

init/main.c 안에서 부트로더에 의해서 전달된 커널 커맨드 문자열은

char __initdata boot_command_line[COMMAND_LINE_SIZE];

에 저장됩니다.

 

그러므로 이 변수를 출력해 보면 됩니다.

 

앞에서 추가 했던 문자 바로 뒤에 다음과 같이 추가 합니다.

 

[init/main.c]

622         /*
623          * HACK ALERT! This is early. We're enabling the console before
624          * we've done PCI setups etc, and console_init() must be aware of
625          * this. But we do want output early, in case something goes wrong.
626          */
627
628         TRACE_LINE
629         printascii( boot_command_line );
630
631         console_init();



커널을 컴파일 하고 어떻게 되나 봅시다.

Copy Kernel Image .....
Starting kernel [MARCH 110]...
kernel command [EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200    ip0=192.168.10.182 mac=00:FA:07:78:65:05 netmask=255.255.255.0 gw=192.168.10.1 host=192.168.10.61 nandparts=1,8,55 ]
Uncompressing Linux...................................................................................... done, booting the kernel.

>>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
>>TRACE init/main.c:start_kernel:628root=/dev/nfs ip=dhcp console=ttyS0,115200 mem=64M


뭔가 이상합니다.

 

이지부트에서 전달된 커널 커맨드와 다르죠?

 

이건 아무래도 부트 파라메터 전달과정에서의 오류인 것 같은데 ..

arch/arm/mach-pxa/idp.c

을 살펴보아야 할 것 같습니다.

 

랄랄랄~~~

열라 소스 보는 중…

 

헉~~

 

뭔가 이상합니다.

 

보시겠습니까?


MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
        /* Maintainer: Vibren Technologies */
        .phys_io        = 0x40000000,
        .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = idp_map_io,
        .init_irq       = pxa25x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = idp_init,
MACHINE_END


부트로더와 커널이 서로 데이터를 교환하기 위해서는 부트파람 영역에 주소를 전달해야 하는데 위 부분 중 이에 해당하는 부분이 없습니다.

 

허허~~

 

아무래도 원인을 발견한 것 같습니다.

 

다음과 같이 부트 파라메터 영역을 위 부분에 추가 합니다.

.boot_params    = 0xa0000100,


   208 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
    209         /* Maintainer: Vibren Technologies */
    210         .phys_io        = 0x40000000,
    211         .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
    212         .boot_params    = 0xa0000100,
    213         .map_io         = idp_map_io,
    214         .init_irq       = pxa25x_init_irq,
    215         .timer          = &pxa_timer,
    216         .init_machine   = idp_init,
    217 MACHINE_END

자 커널을 컴파일 하고

보드에 다시 올려서 부팅해 봅시다.

두근 두근…

그러나…

>>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
>>TRACE init/main.c:start_kernel:628EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200    ip0=192.168.10.182 mac=00:FA:07:78:65:05 netmask=255.255.255.0 gw=192.168.10.1 host=192.168.10.61 nandparts=1,8,55


예 커널 커맨드는 제대로 전달되었지만 여전히 나오지 않습니다.

 

이제 확인해 볼 것은 두 가지 정도 있습니다.

 

console= 에 지정할 수 있는 디바이스 명이 정말 ttyS2 인가 하는 부분과

arch/arm/mach-pxa/idp.c 에서 등록한 디바이스 중 EZ-X5에 없어서 트러블이 생기는
디바이스로 인한 멈춤인가를 보는 것입니다.

 

여러분은 어떤 부분부터 의심하고 싶으십니까?

 

저 같으면 EZ-X5에 없는 장치의 동작으로 인한 멈춤에 100원 걸겠습니다.


 

LED 나 프레임 버퍼를 의심하자

우선 디바이스 드라이버나 다른 장치에 의해서 멈추는 가를 확인하고 싶다면 TRACE_LINE 매크로의 도움을 받아서 좀 더 추적해 봐야 할 듯 합니다.

 

각 함수가 어떤 식으로 흘러 가는 가를 설명하는 것은 제가 귀차니즘이 발생합니다. ㅠㅠ 그래서 결론만 말씀 드리면

do_basic_setup();

커널 함수가 있는데 이 함수를 통과 하는 가를 확인해 봐야 합니다.

이 부분에서 멈추면 대부분의 경우 하드웨어 제어 디바이스 드라이버의 문제 입니다

.

그래서 이 함수 앞뒤에  TRACE_LINE 매크로로 삽입 해 보겠습니다.

 

[init/main.c]

866         smp_init();
867         sched_init_smp();
868
869         cpuset_init_smp();
870         TRACE_LINE
871         do_basic_setup();
872         TRACE_LINE
873
874         /*
875          * check if there is an early userspace init.  If yes, let it do all
876          * the work
877          */
878
879         if (!ramdisk_execute_command)


커널 컴파일 하고 보드 재 부팅해 봅니다.

>>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
>>TRACE init/main.c:start_kernel:628EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200    ip0=192.168.10.182 mac=00:FA:07:78:65:05 netmask=255.255.255.0 gw=192.168.10.1 host=192.168.10.61 nandparts=1,8,55
>>TRACE init/main.c:kernel_init:870



역쉬….

 

하드웨어 트러블이 범인이라는 냄새가 진하게 나는 군요.. 후후…

 

자 그렇다면 도대체 어떤 디바이스 드라이버일까요?

 

저야 어떤 놈이 문제를 일으킬까 하는 것을 추적하는 방법을 알고 있지만

여기서 찾아 보는 방법을 알아내는 것도 무척 귀찮네요..

 

그래서 일반적인 포팅 경험에서 우러나는 ..

즉 족집게 찌기를 알려 드리죠…

 

대부분의 경우 이런 경우에 생각외로 LED 와 프레임버퍼 설정에서 문제가 많이 발생합니다.

 

그래서 저는 다음과 같이 우선적으로 커널 컴파일 옵션을 이용하여 LED 설정 부분과 프레임 버퍼 설정을 비 활성화 하기를 강하게 권합니다.

 

한번 해 봅시다.

 

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

 

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

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


이렇게 쓴것이 어떤 의미인지는 알겠지요?

 

화면 캡쳐 하기 싫어서 그런 겁니다.

 

알아서들 하시고 컴파일 해 보고 다시 부팅해 봅시당.

 

> 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.2.50 (FALINUX Co.,Ltd) ..........PXA255(EZ-X5)
Program by You Young-chang, Oh Jae-Kyoung, Jang Hyung-Gi
Last Modify Aug 19 2008

  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)

                                                             
Copy Kernel Image .....
Starting kernel [MARCH 110]...
kernel command [EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200    ip0=192.168.10.182 mac=00:FA:07:78:65:05 netmask=255.255.255.0 gw=192.168.10.1 host=192.168.10.61 nandparts=1,8,55 ]
Uncompressing Linux.................................................................................... done, booting the kernel.

>>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
>>TRACE init/main.c:start_kernel:628EZBOOT mem=64M initrd=0xA0800000,5M root=/dev/ram ramdisk=16384 console=ttyS2,115200    ip0=192.168.10.182 mac=00:FA:07:78:65:05 netmask=255.255.255.0 gw=192.168.10.1 host=192.168.10.61 nandparts=1,8,55
>>TRACE init/main.c:kernel_init:870Linux version 2.6.28.10 (root@localhost.localdomain) (gcc version 3.4.3) #51 Sun Jul 5 10:02:58 EDT 2009
CPU: XScale-PXA255 [69052d06] revision 6 (ARMv5TE), cr=0000397f
CPU: VIVT data cache, VIVT instruction cache
Machine: Vibren PXA255 IDP
Memory policy: ECC disabled, Data cache writeback
Memory clock: 99.53MHz (*27)
Run Mode clock: 398.13MHz (*4)
Turbo Mode clock: 398.13MHz (*1.0, inactive)
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    ip0=192.168.10.182 mac=00:FA:07:78:65:05 netmask=255.255.255.0 gw=192.168.10.1 host=192.168.10.61 nandparts=1,8,55
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: 62224KB available (2376K code, 185K data, 84K init)
SLUB: Genslabs=12, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Calibrating delay loop... 397.31 BogoMIPS (lpj=1986560)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 288 bytes
NET: Registered protocol family 16
idp_init()
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
pxa2xx-uart.3: ttyS3 at MMIO 0x41600000 (irq = 7) is a HWUART
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 DSP coprocessor detected.

>>TRACE init/main.c:kernel_init:872VFS: 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)



어무이…

 

부팅해 부럿습니당…

아하하하…

 

마지막에 보이시죠

 

>>TRACE init/main.c:kernel_init:872

 

이놈까지 통과 한 것이죠. ㅋㅋ

 

자 이제 디버그 메시지를 모두 제거 하고 커밋 하죠…

어디를 제거 해야 하더라.. 쩝…

뭐 제가 잘 알아서 제거 하고 SVN 에 커밋하려 합니다.

 

그리고 현재 환경 설정도 저장해야 겠죠?

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

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

커널을 클리어 합니다.

 [root@localhost linux]# make clean

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

[root@localhost linux]# svn st

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

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

서브 버전에 커밋 합니다.

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

아… 힘들었습니다.