串口执行流程,首先是/common/board_f.c中
先调用
void board_init_f(ulong boot_flags)
该函数是汇编代码进入C代码前在_main中调用的地址重定向前的设备初始化函数,其中调用
initcall_run_list(init_sequence_f)
来执行init_sequence_f数组中的相关初始化函数,该数组的定义也在本文件中,其定义如下
static init_fnc_t init_sequence_f[]
该序列中关于串口的函数主要有
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
第一个是初始化初始化波特率,注意这里的初始化波特率并不是设置串口波特率,而是先查找环境变量区看是否存在波特率,若不存在根据宏定义来将波特率保存在全局数据(global data)其函数实现如下:
static int init_baud_rate(void)
{
gd->baudrate = getenv_ulong("baudrate", 10, CONFIG_BAUDRATE);
return 0;
}
第二个函数为串口初始化,主要关于硬件初始化,其实现函数如下:
int serial_init(void)
{
return get_current()->start();
}
该函数位于driver/serial/serial.c中,其中get_current()函数实现如下:
static struct serial_device *get_current(void)
{
struct serial_device *dev;
if (!(gd->flags & GD_FLG_RELOC))
dev = default_serial_console();
else if (!serial_current)
dev = default_serial_console();
else
dev = serial_current;
/* We must have a console device */
if (!dev) {
#ifdef CONFIG_SPL_BUILD
puts("Cannot find console\n");
hang();
#else
panic("Cannot find console\n");
#endif
}
return dev;
}
该函数位于本文件中,其大致实现过程为,若第一次初始化串口(即在重定向前初始化串口),则将设备执行默认串口default_serial_console,若在重定向后再次初始化串口,则查找当前串口设备。其中default_serial_console实现函数如下:
__weak struct serial_device *default_serial_console(void)
{
#if CONFIG_CONS_INDEX == 1
return &eserial1_device;
#elif CONFIG_CONS_INDEX == 2
return &eserial2_device;
#elif CONFIG_CONS_INDEX == 3
return &eserial3_device;
#elif CONFIG_CONS_INDEX == 4
return &eserial4_device;
#elif CONFIG_CONS_INDEX == 5
return &eserial5_device;
#elif CONFIG_CONS_INDEX == 6
return &eserial6_device;
#else
#error "Bad CONFIG_CONS_INDEX."
#endif
}
其中在全志的config配置文件即sun50iw101.h中定义了CONFIG_CONS_INDEX为1,故我们使用eserial1_device这个设备,继续查找eserial1_device的函数如下:
#if defined(CONFIG_SYS_NS16550_COM1)
DECLARE_ESERIAL_FUNCTIONS(1);
struct serial_device eserial1_device =
INIT_ESERIAL_STRUCTURE(1, "eserial0");
#endif
#if defined(CONFIG_SYS_NS16550_COM2)
DECLARE_ESERIAL_FUNCTIONS(2);
struct serial_device eserial2_device