1. 程式人生 > >移植linux核心到s3c6410(kernel 列印:Uncompressing Linux ... done , booting the kernel.後無響應問題的解決。)

移植linux核心到s3c6410(kernel 列印:Uncompressing Linux ... done , booting the kernel.後無響應問題的解決。)

轉載地址: https://blog.csdn.net/roadtoforest/article/details/6652280

U-boot網口問題解決後,uImage和ramdisk終於可以上傳到單板上去驗證了。指令碼為:

MINI6410 # setenv serverip 192.168.1.200
 
MINI6410 # setenv bootargs root=/dev/ram rootfstype=ext2 init=/linuxrc console=ttySAC0,115200 mem=256
 
MINI6410 # tftp 0x51800000 ramdisk.bin

MINI6410 # tftp 0x50800000 uImage

MINI6410 # bootm 0x50800000 0x51800000
————————————————————————————————————————————————————————
————————————————————————————————————————————————————————
執行bootm命令後列印:

## Booting image at 50800000 ...
   Image Name:   Linux-2.6.38
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1902992 Bytes =  1.8 MB
   Load Address: 50008000
   Entry Point:  50008000
   Verifying Checksum ... OK
OK
## Loading Ramdisk Image at 51800000 ...
   Image Name:   ramdisk1.0
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    1040870 Bytes = 1016.5 kB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
 
Starting kernel ...
 
Uncompressing Linux... done, booting the kernel.
 
就無任何反應了!!!!網上查資料主要懷疑方向有:
1、machine ID uboot與核心定義不一致。
2、核心引數console傳遞的不對。
 
問題確認:
1、machine ID uboot與核心定義不一致。
uboot傳遞的machine ID引數:
board\samsung\mini6410\Mini6410.c
 gd->bd->bi_arch_number = MACH_TYPE;
include/configs/Mini6410.h
#define MACH_TYPE  2520
核心的machine ID引數:
include/generated/mach-types.h
#define MACH_TYPE_MINI6410             2520
所以不是這個問題。

 
2、核心引數console傳遞的不對。
console=ttySAC0,115200 這個也確認是沒有問題。
所以也不是這個問題。
 
————————————————————————————————————————————————————————
————————————————————————————————————————————————————————

沒辦法,只能自己動手除錯了。
 
1、首先嚐試low-level debug除錯方法
Kernel hacking-->Kernel low-level debugging functions
Kernel hacking-->S3C UART to use for low-level debug 為UART 0。
可是問題依舊,還是無任何列印。
 
2、直接使用printascii/printhex8 列印kernel啟動過程。
printascii其實就是1個字元1個字元往串口裡寫,addruart_current 就是返回當前uart的暫存器基地址,這個與我們前面的S3C UART to use for low-level debug 配置有關。
       ENTRY(printascii)
  addruart_current r3, r1, r2
  b 2f
1:  waituart r2, r3
  senduart r1, r3
  busyuart r2, r3
  teq r1, #'\n'
  moveq r1, #'\r'
  beq 1b
2:  teq r0, #0
  ldrneb r1, [r0], #1
  teqne r1, #0
  bne 1b
  mov pc, lr
ENDPROC(printascii)
printhex8 其實就是將16進位制數,每4個bit為1個字元,填寫到buffer裡,即轉為 ASCII字串,然後呼叫printascii打印出來。
我寫的定位函式,r0為入參,列印具體到了哪一步:
__right_p:
    adr r13,spbuf1
    STMIA r13, {R1-R4,R7}
    mov r7,lr
    mov r4, r0
    adr r0, str_p3
    bl     printascii
    mov r0 ,r4
    bl printhex8
    adr r0,str_p4
    bl printascii
    mov lr,r7
    ldmia r13,{R1-R4,R7}
    mov pc,lr
    str_p3: .asciz "\nkernel boot step 0x"
    str_p4:      .asciz     "\n"
 .align
ENDPROC(__right_p)
spbuf1:  .space 20
例如:
/*step 0*/
      mov r0,#0
      bl __right_p
寫彙編函式要注意幾點:
A、破壞的暫存器一定要儲存
B、多層呼叫(a-->b-->c)一定要記得儲存/恢復lr暫存器,因為b呼叫c是會破壞a的返回地址。
 
加了定位資訊後:

Starting kernel ...
 
Uncompressing Linux... done, booting the kernel.
 
kernel boot step 0x00000000
000009d8
7f005000
c0008358
50025288
500252c0
000009d8
 
kernel boot step 0x00000001
 
kernel boot step 0x00000002
 
kernel boot step 0x00000003
 
kernel boot step 0x00000004
確認了:
machine ID確實是對的。
異常不是在彙編階段而是出在start_kernel函式之後。
繼續在start_kernel里加列印,終於確定是在 setup_arch(&command_line);之後就出現異常了。但是還是無法精確定位,由於在 console_init();初始化之前printk是列印在__log_buf裡,而且在軟復位或者按鍵復位後,記憶體的值還能保留,所以嘗試按鍵復位後,在uboot裡使用md命令檢視__log_buf裡的值來確認核心初始化的列印。

__log_buf=503c9598

MINI6410 # md 0x503c9598
503c9598: 4c3e353c 78756e69 72657620 6e6f6973    <5>Linux version
503c95a8: 362e3220 2038332e 6f6f7228 6f6c4074     2.6.38 ([email protected]
503c95b8: 686c6163 2e74736f 61636f6c 6d6f646c    calhost.localdom
503c95c8: 296e6961 63672820 65762063 6f697372    ain) (gcc versio
503c95d8: 2e34206e 20332e34 6e746328 2e312d67    n 4.4.3 (ctng-1.
503c95e8: 29312e36 23202920 53203432 4a206e75    6.1) ) #24 Sun J
503c95f8: 32206c75 32322034 3a35343a 43203333    ul 24 22:45:33 C
503c9608: 32205453 0a313130 433e343c 203a5550    ST 2011.<4>CPU: 
503c9618: 764d5241 6f632d36 7461706d 656c6269    ARMv6-compatible
503c9628: 6f727020 73736563 5b20726f 66303134     processor [410f
503c9638: 36363762 6572205d 69736976 36206e6f    b766] revision 6
503c9648: 52412820 2937764d 7263202c 6330303d     (ARMv7), cr=00c
503c9658: 37383335 343c0a66 5550433e 4956203a    5387f.<4>CPU: VI
503c9668: 6e205450 6c616e6f 69736169 6420676e    PT nonaliasing d
503c9678: 20617461 68636163 56202c65 20545049    ata cache, VIPT 
503c9688: 616e6f6e 7361696c 20676e69 74736e69    nonaliasing inst
MINI6410 # 
503c9698: 74637572 206e6f69 68636163 00000a65    ruction cache...
503c96a8: 00000000 00000000 00000000 00000000    ................
503c96b8: 00000000 00000000 79726f6d 6c6f7020    ........mory pol
503c96c8: 3a796369 43434520 73696420 656c6261    icy: ECC disable
503c96d8: 44202c64 20617461 68636163 72772065    d, Data cache wr
503c96e8: 62657469 0a6b6361 4b3e303c 656e7265    iteback.<0>Kerne
503c96f8: 6170206c 2063696e 6f6e202d 79732074    l panic - not sy
503c9708: 6e69636e 45203a67 524f5252 6146203a    ncing: ERROR: Fa
503c9718: 64656c69 206f7420 6f6c6c61 65746163    iled to allocate
503c9728: 31783020 20303030 65747962 65622073     0x1000 bytes be
503c9738: 20776f6c 2e307830 3e303c0a 3e343c0a    low 0x0..<0>.<4>
503c9748: 6b636142 63617274 0a203a65 5b3e343c    Backtrace: .<4>[
503c9758: 3030633c 37363133 205d3e63 6d756428    <c003167c>] (dum
503c9768: 61625f70 72746b63 2b656361 2f307830    p_backtrace+0x0/
503c9778: 31317830 66202934 206d6f72 30633c5b    0x114) from [<c0
503c9788: 61306332 5d3e3436 75642820 735f706d    2c0a64>] (dump_s
MINI6410 # md 0x503c9598             
503c9798: 6b636174 3178302b 78302f38 0a296331    tack+0x18/0x1c).
503c97a8: 00000000 00000000 00000000 00000000    ................
503c97b8: 00000000 00000000 00346163 00000000    ........ca4.....
503c97c8: 00000000 00000000 00000000 00000000    ................
503c97d8: 00000000 00000000 6d756428 74735f70    ........(dump_st
503c97e8: 2b6b6361 2f307830 63317830 72662029    ack+0x0/0x1c) fr
503c97f8: 5b206d6f 3230633c 63613063 205d3e63    om [<c02c0acc>] 
503c9808: 6e617028 302b6369 2f343678 38317830    (panic+0x64/0x18
503c9818: 000a2930 00000000 63323063 38366130    0)......c02c0a68
503c9828: 28205d3e 696e6170 78302b63 78302f30    >] (panic+0x0/0x
503c9838: 29303831 6f726620 3c5b206d 31303063    180) from [<c001
503c9848: 38653936 28205d3e 626d656d 6b636f6c    69e8>] (memblock
503c9858: 6c6c615f 625f636f 2b657361 63337830    _alloc_base+0x3c
503c9868: 3478302f 000a2930 00000000 00000000    /0x40)..........
503c9878: 00000000 00000000 30303a32 30303030    ........2:000000
503c9888: 00003030 00000000 00000000 00000000    00..............
MINI6410 # 
503c9898: 00000000 00000000 00006232 00000000    ........2b......
503c98a8: 00000000 00000000 00000000 00000000    ................
503c98b8: 00000000 00000000 625f636f 2b657361    ........oc_base+
503c98c8: 2f307830 30347830 72662029 5b206d6f    0x0/0x40) from [
503c98d8: 3030633c 33613631 205d3e34 6d656d28    <c0016a34>] (mem
503c98e8: 636f6c62 6c615f6b 2b636f6c 34317830    block_alloc+0x14
503c98f8: 3178302f 000a2938 72203e34 30633a35    /0x18)..4> r5:c0
503c9908: 31353134 00006338 00000000 00000000    41518c..........
503c9918: 00000000 00000000 31303063 30326136    ........c0016a20
503c9928: 28205d3e 626d656d 6b636f6c 6c6c615f    >] (memblock_all
503c9938: 302b636f 302f3078 29383178 6f726620    oc+0x0/0x18) fro
503c9948: 3c5b206d 30303063 63306464 28205d3e    m [<c000dd0c>] (
503c9958: 39332e54 78302b31 302f3831 29303378    T.391+0x18/0x30)
503c9968: 0000000a 00000000 00000000 00000000    ................
503c9978: 00000000 00000000 2f307830 30337830    ........0x0/0x30
503c9988: 72662029 5b206d6f 3030633c 32376530    ) from [<c000e72
 
發現一條異常列印:
Kerne  panic - not syncing: ERROR: Failed to allocate 0x1000 bytes be low 0x0..
搜尋程式碼中的列印,確認是這個函式裡列印的:
start_kernel-->setup_arch-->paging_init-->bootmem_init-->arm_bootmem_init-->memblock_alloc_base
phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
{
 phys_addr_t alloc;
 alloc = __memblock_alloc_base(size, align, max_addr);
 if (alloc == 0)
  panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
        (unsigned long long) size, (unsigned long long) max_addr);
 return alloc;
}
 
這裡分配出了問題,懷疑是struct meminfo meminfo;的初始化出問題了,所以繼續使用printascii/printhex8在各個階段列印這個結構
u.mem.start=50000000
u.mem.size=10000000
 
1
r_banks=00000001
start=50000000
u.mem.size=10000000
root=/dev/ram rootfstype=ext2 init=/linuxrc console=ttySAC0,115200 mem=256
 
2
r_banks=00000000
start=50000000
u.mem.size=00000000
 
3
r_banks=00000000
start=50000000
u.mem.size=00000000
OK
 
發現是 parse_early_param();之後就r_banks=00000000確認記憶體解析函式
early_mem-->memparse
unsigned long long memparse(const char *ptr, char **retptr)
{
 char *endptr; /* local pointer to end of parsed string */
 unsigned long long ret = simple_strtoull(ptr, &endptr, 0);
 switch (*endptr) {
 case 'G':
 case 'g':
  ret <<= 10;
 case 'M':
 case 'm':
  ret <<= 10;
 case 'K':
 case 'k':
  ret <<= 10;
  endptr++;
 default:
  break;
 }
 if (retptr)
  *retptr = endptr;
 return ret;
}
 
size返回是0,終於發現竟然是我的boot args裡的mem=256少了個M,悲劇!!!!!
 
————————————————————————————————————————————————————————
————————————————————————————————————————————————————————

總結一下console_init終端初始化前的定位方法:
1、使用low_level debug的printascii/printhex8做除錯列印。
核心配置:
Kernel hacking-->Kernel low-level debugging functions
Kernel hacking-->S3C UART to use for low-level debug 選擇UART num。
2、打印出來printk的__log_buf的實體地址的值,軟復位或者按鍵復位後在uboot裡使用md 這個實體地址檢視列印內容。
             printklogbuf = __pa(__log_buf);
        printascii("\n__log_buf=");
       printhex8(printklogbuf);
       printascii("\n");

 
記憶體引數傳遞:
ATAG_MEM 
uboot裡在armlinux.c的setup_memory_tags裡處理,bd->bi_dram[i].start和bd->bi_dram[i].size通常在自己單板的board檔案裡的dram_init來賦值:
#ifdef CONFIG_SETUP_MEMORY_TAGS
static void setup_memory_tags (bd_t *bd)
{
 int i;
 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
  params->hdr.tag = ATAG_MEM;
  params->hdr.size = tag_size (tag_mem32);
  params->u.mem.start = bd->bi_dram[i].start;
  params->u.mem.size = bd->bi_dram[i].size;
  params = tag_next (params);
 }
}
#endif /* CONFIG_SETUP_MEMORY_TAGS */
 核心在這裡解析:setup_arch-->parse_tags-->parse_tag_mem32
parse_tags就是根據傳遞引數裡的tags標記,然後選擇各種解析函式進行解析,記憶體解析就是新增記憶體分割槽,即修改struct meminfo meminfo的內容
static int __init parse_tag_mem32(const struct tag *tag)
{
     return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}
bootargs:
mem=xM或者其它單位,bootargs是在parse_tags-->parse_tag_cmdline拷貝到核心default_command_line裡的,然後在setup_arch--> parse_early_param();解析裡面的各個引數,記憶體就是通過這個early_mem函式來解析的。
 
優先順序:
bootargs>ATAG_MEM。也就是如果在bootargs裡面定義了mem=就以bootargs裡面為準,因為這個使用者定義的
--------------------- 
作者:一身技術 
來源:CSDN 
原文:https://blog.csdn.net/roadtoforest/article/details/6652280 
版權宣告:本文為博主原創文章,轉載請附上博文連結!