日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

全志A33-linux内核early_printk分析及使用

發布時間:2023/12/15 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 全志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分析及使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。