linux的early printk的探讨

http://mcuos.com/thread-8169-1-1.html

(一)知识背景:

  1. [color=Red]Uncompressing Linux... done, booting the kernel.
  2. ------------setup_arch------------
  3. ------------setup_machine_fdt return 0------------
  4. Machine: MCUOS6410[/color]
  5. Linux version 3.0.30-g4e794c6-dirty (zswan@zswan-laptop-ubuntu) (gcc version 4.2.1) #17 Sun May 6 00:55:44 CST 2012
  6. bootconsole [earlycon0] enabled
  7. S3C24XX Clocks, Copyright 2004 Simtec Electronics
  8. camera: no parent clock specified
  9. S3C64XX: PLL settings, A=532000000, M=532000000, E=24000000
  10. S3C64XX: HCLK2=266000000, HCLK=133000000, PCLK=66500000
  11. mout_apll: source is fout_apll (1), rate is 532000000
  12. mout_epll: source is epll (1), rate is 24000000

复制代码



我们知道line 5-12行代码部分, 是 printk打印出来的。而如果你想要在打印linux的版本之前的 函数 line1-4行中也加打印信息,那么printk这个时候其实 串口 ,console什么的还没注册呢,所以肯定没有信息的。比如说,我想打印setup函数中的部分 调试 信息:

  1. void __init setup_arch(char **cmdline_p)
  2. {
  3.         struct machine_desc *mdesc;
  4.         unwind_init();
  5.         setup_processor();
  6.         early_printk("------------setup_arch------------\n");
  7.         //return ;
  8.         mdesc = setup_machine_fdt(__atags_pointer);
  9.         early_printk("------------setup_machine_fdt return %d------------\n", mdesc);
  10.         if (!mdesc)
  11.                 mdesc = setup_machine_tags(machine_arch_type);
  12.         machine_desc = mdesc;
  13.         machine_name = mdesc->name;
  14. early_printk("Machine: %s\n", machine_name);
  15.         if (mdesc->soft_reboot)
  16.                 reboot_setup("s");

复制代码

就可以使用early printk的功能啦,那么 如何 打开这个功能呢,下面我做个介绍:
(二)支持early printk对内核需要做的配置
(1)Kernel hacking  ---> Kernel low-level debugging functions -->   Early printk 
(2)boot option中你需要添加 earlyprintk项。类似于:
root=/dev/ram0 console=ttySAC0,115200n8 rdinit=/sbin/init earlyprintk

(三)在需要加打印信息的地方使用early_printk函数代替printk函数。
(四)对early printk的驱动实现的分析

arch/arm/kernel/early_printk.c文件,上代码:
 

  1. extern void printch(int);
  2. static void early_write(const char *s, unsigned n)
  3. {
  4.         while (n-- > 0) {
  5.                 if (*s == '\n')
  6.                         printch('\r');
  7.                 printch(*s);
  8.                 s++;
  9.         }
  10. }
  11. static void early_console_write(struct console *con, const char *s, unsigned n)
  12. {
  13.         early_write(s, n);
  14. }
  15. static struct console early_console = {
  16.         .name =                "earlycon",
  17.         .write =        early_console_write,
  18.         .flags =        CON_PRINTBUFFER | CON_BOOT,
  19.         .index =        -1,
  20. };
  21. asmlinkage void early_printk(const char *fmt, ...)
  22. {
  23.         char buf[512];
  24.         int n;
  25.         va_list ap;
  26.         va_start(ap, fmt);
  27.         n = vscnprintf(buf, sizeof(buf), fmt, ap);
  28.         early_write(buf, n);
  29.         va_end(ap);
  30. }
  31. static int __init setup_early_printk(char *buf)
  32. {
  33.         register_console(&early_console);
  34.         return 0;
  35. }
  36. early_param("earlyprintk", setup_early_printk);

复制代码




其实这段code最终的实现都是靠:extern void printch(int);这个函数。这个函数实现是在:


arch/arm/kernel/debug.S中:

  1. ENTRY(printch)
  2.                 addruart_current r3, r1, r2
  3.                 mov        r1, r0
  4.                 mov        r0, #0
  5.                 b        1b
  6. ENDPROC(printch)

复制代码



 

  1.                 .macro        addruart_current, rx, tmp1, tmp2
  2.                 addruart        \tmp1, \tmp2
  3.                 mrc                p15, 0, \rx, c1, c0
  4.                 tst                \rx, #1
  5.                 moveq                \rx, \tmp1
  6.                 movne                \rx, \tmp2
  7.                 .endm

复制代码





printch会调用到 addruart_current函数,而addruart_current函数用调用到:addruart函数,该函数实现是在:
arch\arm\mach-s3c64xx\ include \mach中的debug-macro.S汇编文件中:

 

  1.         .macro addruart, rp, rv
  2.                 ldr        \rp, = S3C_PA_UART
  3.                 ldr        \rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)
  4. #if CONFIG_DEBUG_S3C_UART != 0
  5.                 add        \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)
  6.                 add        \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)
  7. #endif
  8.         .endm

复制代码





我们从上面的代码可以看到S3C_PA_UART, S3C_PA_UART都是实际的6410的串口 寄存器 物理和虚拟地址,从而进行真正的 硬件 底层操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值