分类: LINUX
2016-01-27 11:55:51
# vim build_dir/target-mips_34kc_musl-1.1.11/linux-ar71xx_generic/linux-4.1.15/.config (NOTE: 上述.config,由target/linux/ar71xx/config-4.1、target/linux/generic/config-4.1 和Openwrt框架产生的.config 共同作用所得,其产生的具体过程可参考include/*.h, 这里不加以介绍) CONFIG_EARLY_PRINTK=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DMA=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_EARLYCON=y CONFIG_SERIAL_8250_NR_UARTS=1 CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_AR933X=y CONFIG_SERIAL_AR933X_CONSOLE=y CONFIG_SERIAL_AR933X_NR_UARTS=2 |
Starting kernel ... [ 0.000000] Linux version 4.1.15 (gcc version 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 r46919) ) #1 Tue Jan 26 17:07:14 CST 2016 [ 0.000000] bootconsole [early0] enabled #NOTE: 进入内核后立即打开early print端口 [ 0.000000] Kernel command line: board=PIONEER-9531 console=ttyS0,115200 rootfstype=squashfs,jffs2 noinitrd #NOTE: 注意串口名称为ttyS0 .... .... [ 0.640000] Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled [ 0.650000] console [ttyS0] disabled [ 0.670000] serial8250.0: ttyS0 at MMIO 0x18020000 (irq = 11, base_baud = 1562500) is a 16550A [ 0.680000] console [ttyS0] enabled [ 0.680000] console [ttyS0] enabled [ 0.690000] bootconsole [early0] disabled [ 0.690000] bootconsole [early0] disabled |
--/arch/mips/kernel/early_printk.c extern void prom_putchar(char); static void early_console_write(struct console *con, const char *s, unsigned n) { while (n-- && *s) { if (*s == '\n') prom_putchar('\r'); prom_putchar(*s); s++; } } static struct console early_console_prom = { #NOTE:此处定义一个console设备 .name = "early", .write = early_console_write, .flags = CON_PRINTBUFFER | CON_BOOT, .index = -1 }; void __init setup_early_printk(void) #NOTE: early console初始化入口 { if (early_console) return; early_console = &early_console_prom; register_console(&early_console_prom); #NOTE: early console 注册,启动信息中的bootconsole [early0] enabled 来自kernel/printk/printk.c中注册的该函数。 } --/kernel/printk/prink.c ifdef CONFIG_EARLY_PRINTK struct console *early_console; asmlinkage __visible void early_printk(const char *fmt, ...) { va_list ap; char buf[512]; int n; if (!early_console) return; va_start(ap, fmt); n = vscnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); early_console->write(early_console, buf, n); #NOTE: early_printk函数的最终调用的是 early_console->write. #endif |
--/arch/mips/kernel/setup.c void __init setup_arch(char **cmdline_p) { cpu_probe(); prom_init(); setup_early_fdc_console(); #ifdef CONFIG_EARLY_PRINTK setup_early_printk(); #NOTE: 此处调用了/arch/mips/kernel/early_printk.c中的early console的注册接口,该接口包含一个配置控制选项CONFIG_EARLY_PRINTK。 #endif ...... } |
--/init/main.c asmlinkage __visible void __init start_kernel(void) { ....... pr_notice("%s", linux_banner); #NOTE:此语句貌似是一个关键,该打印输出位于early print之前,且也能正常的打出内核的banner,即上面打印信息的“Linux version ..."语句, 此处是直接输出到串口,还是输出到缓冲区待early print初始化完成后再从缓冲区输出来呢? 要想直到这个结果,有一个简单的方法,在 两个语句之间加上一个死循环,看输出信息是否包含banner即可大致确定。 实际上,pr_notice即printk(KERN_NOTICE ....) ,据说其内核实现是由一个环形缓冲区构成,在输出状态没有初始化好了之前,调用的 输出将缓存在环形缓冲区中,待初始化完成以后,再把环形缓冲区的输出信息一并输出,关于环形缓冲区,哪天空了再研究。 setup_arch(&command_line); #NOTE:此处调用了setup_arch()函数 ...... } |
--/arch/mips/ath79/early_printk.c prom_putchar ------> plarform-match ---> static void prom_putchar_ar933x(unsigned char ch) { void __iomem *base = (void __iomem *)(KSEG1ADDR(AR933X_UART_BASE)); prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR, AR933X_UART_DATA_TX_CSR); __raw_writel(AR933X_UART_DATA_TX_CSR | ch, base + AR933X_UART_DATA_REG); prom_putchar_wait(base + AR933X_UART_DATA_REG, AR933X_UART_DATA_TX_CSR, AR933X_UART_DATA_TX_CSR); } |
define Device/pioneer-qca9531-64m-16m $(Device/tplink-16mlzma) BOARDNAME := PIONEER-9531 DEVICE_PROFILE := PIONEER-QCA9531-64M-16M TPLINK_HWID := 0x3C000101 CONSOLE := ttyATH0,115200 #NOTE:注意这里的console名称为ttyATH0 endef |
......... [ 0.690000] bootconsole [early0] disabled |