Zephyr printk实现介绍

zephyr printk的实现分为两步:

1、字符输出函数console_out()的实现

2、printk()的实现

printk()通过格式化字符串,并调用console_out()实现了打印的效果。

 

以下详细说明:

一、字符输出函数console_out()的实现

1、初始化uart作为log输出的物理接口。(device_get_binding初始化外设属于设备树模型,以后会写另一篇博客详细介绍,此处只要知道该API初始化了uart即可)

 1 static int uart_console_init(const struct device *arg)
 2 {
 3 
 4     ARG_UNUSED(arg);
 5 
 6     /* Claim console device */
 7     uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
 8 
 9     uart_console_hook_install();
10 
11     return 0;
12 }
 
2、字符发送API:console_out被注册到printk.c文件夹下的_char_out函数。(注意:_char_out最终会被printk调用)
//drivers/console/uart_console.c
 1 static void uart_console_hook_install(void)
 2 {
 3     __stdout_hook_install(console_out);
 4     __printk_hook_install(console_out);
 5 }
 6 //lib/os/printk.c
 7 void __printk_hook_install(int (*fn)(int))
 8 {
 9     _char_out = fn;   //_char_out  = console_out
10 }

//
console_out()调用串口API:uart_poll_out发送字符
static int console_out(int c)
{
#ifdef CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS

    int handled_by_debug_server = HANDLE_DEBUG_HOOK_OUT(c);

    if (handled_by_debug_server) {
        return c;
    }

#endif  /* CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS */

    if ('\n' == c) {
        uart_poll_out(uart_console_dev, '\r');
    }
    uart_poll_out(uart_console_dev, c);

    return c;
}

 

二、printk()的实现

_char_out是发送字符的函数,被注册到char_out中了。

cbvprintf调用char_out发送字符。printk逐级调用到cbvprintf。

 1 void printk(const char *fmt, ...)
 2 {
 3     va_list ap;
 4 
 5     va_start(ap, fmt);
 6 
 7     if (IS_ENABLED(CONFIG_LOG_PRINTK)) {
 8         log_printk(fmt, ap);
 9     } else {
10         vprintk(fmt, ap);
11     }
12     va_end(ap);
13 }
14 
15 void vprintk(const char *fmt, va_list ap)
16 {
17     struct out_context ctx = { 0 };
18 #ifdef CONFIG_PRINTK_SYNC
19     k_spinlock_key_t key = k_spin_lock(&lock);
20 #endif
21 
22     cbvprintf(char_out, &ctx, fmt, ap);
23 
24 #ifdef CONFIG_PRINTK_SYNC
25     k_spin_unlock(&lock, key);
26 #endif
27 }
28 
29 static int char_out(int c, void *ctx_p)
30 {
31     struct out_context *ctx = ctx_p;
32 
33     ctx->count++;
34     return _char_out(c);
35 }

 

posted on 2021-08-20 17:05  明日的世界  阅读(465)  评论(0编辑  收藏  举报