OK6410A 开发板 (三) 17 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 串口

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);

  • console_init_f 完成后的printf流程
printf  // lib/vsprintf.c
    puts // common/console.c
        pre_console_puts
        serial_puts
  • console_init_r 完成后的printf流程(且CONFIG_CONSOLE_MUX is not set)
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);
  • console_init_r 完成后的printf流程(且CONFIG_CONSOLE_MUX=y)
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
    _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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值