'2009/07'에 해당되는 글 4건

  1. 2009.07.16 2.6.28 커널로 갈아타기 - EZ-X7 시리얼 포팅 (2)
  2. 2009.07.11 2.6.28 커널로 갈아타기 - EZ-X5 시리얼 포팅 성공
  3. 2009.07.11 2.6.28 커널로 갈아타기 - ARM 커널 부팅 추적
  4. 2009.07.07 2.6.28 커널로 갈아타기 - 부팅 초기 디버그 메시지 표출 (1)
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:46

2.6.28 커널로 갈아타기 - EZ-X5 시리얼 포팅 성공

멈춘 이유가 뭘까요?

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"

아… 힘들었습니다.

Trackback 0 Comment 0
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

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



티스토리 툴바