移植linux内核到s3c6410(kernel 打印:Uncompressing Linux ... done , booting the kernel.后无响应问题的解决。)

时间:2021-12-18 00:10:55

   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 (root@lo

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里面为准,因为这个用户定义的。