本文共 3866 字,大约阅读时间需要 12 分钟。
u-boot 阶段 lowlevel_init 调用了以下函数 实现了 putc ,但不支持 printf spl_config_uart_baudrate uart_asm_init asm_putc board_init_f 调用了以下函数,完成后,支持printf initf_dm init_baud_rate // 查找 环境变量 baudrate gd->baudrate = env_get_ulong("baudrate", 10, 115200); serial_init // 重新设置了一下波特率 serial_find_console_or_panic gd->flags |= GD_FLG_SERIAL_READY; serial_setbrg console_init_f // 该函数执行完后printf 可用了 gd->have_console = 1; console_update_silent print_pre_console_buffer board_init_r 调用了以下函数,提供了多个输出的可能 initr_dm stdio_init_tables INIT_LIST_HEAD(&devs.list); serial_initialize serial_init serial_find_console_or_panic gd->flags |= GD_FLG_SERIAL_READY; serial_setbrg // 为 console 机制 提供 一个 console stdio_add_devices // lcd drv_lcd_init // uart drv_system_init struct stdio_dev dev; memset (&dev, 0, sizeof (dev)); strcpy (dev.name, "serial"); dev.flags = 0x00000002 | 0x00000001; dev.putc = stdio_serial_putc; dev.puts = stdio_serial_puts; dev.getc = stdio_serial_getc; dev.tstc = stdio_serial_tstc; stdio_register (&dev); // 直接插入链表 stdio_register_dev struct stdio_dev *_dev; _dev = stdio_clone(dev); list_add_tail(&_dev->list, &devs.list); serial_stdio_init // null // 组织 所有的 console,并 初始化 console 系统 // 如果 设置了 CONFIG_CONSOLE_MUX is not set , 则填充 stdio_devices[1] , 打印使用 stdio_devices[1]->puts // 如果 设置了 CONFIG_CONSOLE_MUX=y , 则填充 console 链表, 打印的话则 依次调用链表上的 stdio_devices 的 puts 成员 // 下面是 设置了 CONFIG_CONSOLE_MUX is not set 的情况 console_init_r struct stdio_dev *inputdev = 0; struct stdio_dev *outputdev = 0; struct list_head *list = stdio_get_list(); // &devs.list; struct list_head *pos; struct stdio_dev *dev; int flushpoint; if (console_update_silent()) flushpoint = 0; else flushpoint = 1; for (pos = (list)->next; prefetch(pos->next), pos != (list); pos = pos->next) { dev = list_entry(pos, struct stdio_dev, list); if ((dev->flags & 0x00000001) && (inputdev == 0) inputdev = dev; if ((dev->flags & 0x00000002) && (outputdev ==0) outputdev = dev; } console_setfile(1, outputdev); stdio_devices[1] = outputdev; // 填充 gd->jt->putc = putc; // 这个填充为什么不是用 outputdev 的成员填充,而是用 putc 直接填充 console_setfile(2, outputdev); stdio_devices[1] = outputdev; console_setfile(0, inputdev); stdio_devices[0] = inputdev; // 填充 gd->jt->getc stdio_print_current_devices // 打印 In Out Err // 设置环境变量 for (i = 0; i < 3; i++) { env_set(stdio_names[i], stdio_devices[i]->name); } gd->flags |= GD_FLG_DEVINIT; // 打印之前在缓冲区的字符 print_pre_console_buffer(flushpoint);
printf // lib/vsprintf.c puts // common/console.c pre_console_puts serial_puts
printf // lib/vsprintf.c puts // common/console.c fputs // common/console.c console_puts // common/console.c stdio_devices[file]->puts(stdio_devices[file], s);/ 即 stdio_serial_puts serial_puts(s);
printf // lib/vsprintf.c puts // common/console.c fputs // common/console.c console_puts // common/console.c for_each_console_devices_which_has_member_puts dev->puts(dev, s); stdio_serial_puts stdio_lcd_puts ...
serial_puts _serial_puts(gd->cur_serial_dev, str); _serial_putc(dev, *str++); struct dm_serial_ops *ops = serial_get_ops(dev); ops->putc(dev, ch);/即s3c64xx_serial_putc
转载地址:http://abigi.baihongyu.com/