生活随笔
收集整理的這篇文章主要介紹了
全志A33-linux内核early_printk分析及使用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? 分析Linux內核啟動流程時可以知道,在調用setup_arch函數之前就已經調用過printk函數了,但是這個時候的printk函數只是將打印信息放在緩存區中,并沒有打印到控制臺上,因為這個時候控制臺還沒有被初始化。
????? 只有在start_kernel函數中的console_init函數被調用后,控制臺才會被注冊、初始化,printk函數打印的內容才會被真正地輸出到屏幕上。如果想在console_init函數之前打印信息,需要調用early_printk函數。
?
1. 內核配置
(1)Kernel hacking??---> Kernel low-level debugging functions -->? ?Early printk?
(2)boot option中需要添加 earlyprintk項。
類似于:earlyprintk=ttyS0,115200 loglevel=9 initcall_debug=1 console=ttyS0,115200 ramfs
?
2. 使用
在需要打印調試信息的地方調用此函數
early_printk("------------xxx------------\n");
?
3. A33開發板
如在./arch/arm/mach-sunxi/sun8i.c 中有如下語句:
early_printk("[%s]: From boot, get meminfo:\n", __func__);
啟動開發板時串口控制臺信息如下:
在沒有啟用early_printk之前,串口控制臺信息如下:
?
4. 對early printk的驅動實現的分析
arch/arm/kernel/early_printk.c文件,上代碼:
extern void printch(int);?static void early_write(const char *s, unsigned n){? ? ? ? while (n-- > 0) {? ? ? ? ? ? ? ? if (*s == '\n')? ? ? ? ? ? ? ? ? ? ? ? printch('\r');? ? ? ? ? ? ? ? printch(*s);? ? ? ? ? ? ? ? s++;? ? ? ? }}?static void early_console_write(struct console *con, const char *s, unsigned n){? ? ? ? early_write(s, n);}?static struct console early_console = {? ? ? ? .name =? ? ? ? ? ? ? ? "earlycon",? ? ? ? .write =? ? ? ? early_console_write,? ? ? ? .flags =? ? ? ? CON_PRINTBUFFER | CON_BOOT,? ? ? ? .index =? ? ? ? -1,};?asmlinkage void early_printk(const char *fmt, ...){? ? ? ? char buf[512];? ? ? ? int n;? ? ? ? va_list ap;?? ? ? ? va_start(ap, fmt);? ? ? ? n = vscnprintf(buf, sizeof(buf), fmt, ap);? ? ? ? early_write(buf, n);? ? ? ? va_end(ap);}?static int __init setup_early_printk(char *buf){? ? ? ? register_console(&early_console);? ? ? ? return 0;}?early_param("earlyprintk", setup_early_printk);
其實這段code最終的實現都是靠:extern void printch(int);這個函數。這個函數實現是在:arch/arm/kernel/debug.S中:
ENTRY(printch)? ? ? ? ? ? ? ? addruart_current r3, r1, r2? ? ? ? ? ? ? ? mov? ? ? ? r1, r0? ? ? ? ? ? ? ? mov? ? ? ? r0, #0? ? ? ? ? ? ? ? b? ? ? ? 1b?ENDPROC(printch)? ? ? ? ? ? ? ? .macro? ? ? ? addruart_current, rx, tmp1, tmp2? ? ? ? ? ? ? ? addruart? ? ? ? \tmp1, \tmp2? ? ? ? ? ? ? ? mrc? ? ? ? ? ? ? ? p15, 0, \rx, c1, c0? ? ? ? ? ? ? ? tst? ? ? ? ? ? ? ? \rx, #1? ? ? ? ? ? ? ? moveq? ? ? ? ? ? ? ? \rx, \tmp1? ? ? ? ? ? ? ? movne? ? ? ? ? ? ? ? \rx, \tmp2? ? ? ? ? ? ? ? .endm
printch會調用到 addruart_current函數,而addruart_current函數用調用到:addruart函數,該函數實現是在:arch\arm\mach-s3c64xx\include\mach中的debug-macro.S匯編文件中:
? ? ? ? .macro addruart, rp, rv? ? ? ? ? ? ? ? ldr? ? ? ? \rp, = S3C_PA_UART? ? ? ? ? ? ? ? ldr? ? ? ? \rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)#if CONFIG_DEBUG_S3C_UART != 0? ? ? ? ? ? ? ? add? ? ? ? \rp, \rp, #(0x400 * CONFIG_DEBUG_S3C_UART)? ? ? ? ? ? ? ? add? ? ? ? \rv, \rv, #(0x400 * CONFIG_DEBUG_S3C_UART)#endif? ? ? ? .endm
?
?
我們從上面的代碼可以看到S3C_PA_UART, S3C_PA_UART都是實際的6410的串口寄存器物理和虛擬地址,從而進行真正的硬件底層操作。
?
總結
以上是生活随笔為你收集整理的全志A33-linux内核early_printk分析及使用的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。