tiny4412 串口驱动分析三 --- log打印的几个阶段之内核自解压

作者:彭东林

邮箱:[email protected]

 

开发板:tiny4412ADK+S700 4GB Flash

主机:Wind7 64位

虚拟机:Vmware+Ubuntu12_04

u-boot:U-Boot 2010.12

Linux内核版本:linux-3.0.31

Android版本:android-4.1.2

 

内核自解压时期的串口打印

在zImage格式的内核启动时会自解压内核,此时打印信息如下:

Uncompressing Linux...

这句话是在arch/arm/boot/compressed/misc.c中:

void decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, int arch_id) { …… putstr("Uncompressing Linux..."); …… }

 

static void putstr(const char *ptr) { char c; while ((c = *ptr++) != '\0') { if (c == '\n') putc('\r'); putc(c); // 根据APCS规则,c中的值会传给寄存器r0

 } flush(); }

在arch/arm/boot/compressed/.misc.o.cmd中列出了编译misc.c需要依赖那些文件,其中

deps_arch/arm/boot/compressed/misc.o := \ ... arch/arm/mach-exynos/include/mach/uncompress.h \ ... arch/arm/plat-samsung/include/plat/uncompress.h \ ...

在misc.c中有#include <mach/uncompress.h> 指的就是 arch/arm/mach-exynos/include/mach/uncompress.h

在mach/uncompress.h中有:#include <plat/uncompress.h>,指的就是:

arch/arm/plat-samsung/include/plat/uncompress.h

在arch/arm/plat-samsung/include/plat/uncompress.h中有putc的实现:

static void putc(int ch) { if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) { int level; while (1) { level = uart_rd(S3C2410_UFSTAT); level &= fifo_mask; if (level < fifo_max) break; } } else { /* not using fifos */

                   while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE) barrier(); } /* write byte to transmission register */ uart_wr(S3C2410_UTXH, ch); }

 

下面我们看一下uart_rd和uart_wr的实现

static __inline__ void uart_wr(unsigned int reg, unsigned int val) { volatile unsigned int *ptr; ptr = (volatile unsigned int *)(reg + uart_base); *ptr = val; } static __inline__ unsigned int uart_rd(unsigned int reg) { volatile unsigned int *ptr; ptr = (volatile unsigned int *)(reg + uart_base); return *ptr; }

可以看到,使用的是内联函数,并且直接操作的是底层的寄存器,那么到底操作的是哪个uart呢?我们知道,tiny4412有两个可以直接使用的串口,分别对应的是uart0和uart3。想知道这个问题,就需要看uart_base这个变量是什么值?

还是在这个文件中:

#define uart_base S3C_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT)

其中S3C_PA_UART是uart控制器的基地址0x13800000,exynos4412一共有5个uart,每个uart占S3C_UART_OFFSET (0x10000)个字节,还有一个关键的宏CONFIG_S3C_LOWLEVEL_UART_PORT,它就指定了使用哪一个uart,这个宏可以在make menuconfig的时候配置,这里我们设置的是

CONFIG_S3C_LOWLEVEL_UART_PORT=0

 

你可能感兴趣的:(log)