一旦我们发现内核确实在启动,但是控制台没有打印任何内容,就到了开始的时候了。首先,我们强制内核使用指定的串口配置启动,在我们的例子中是9600n1,并且不允许任何命令行选项或启动时间考虑等。
首先要去的地方是drivers/char/tty_io.c,到console_init()。此函数确定启动时的控制台配置。这是一小部分
memset(, 0, sizeof(struct termios)); memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS); tty_std_termios.c_iflag = ICRNL | IGNPAR; tty_std_termios.c_oflag = OPOST | ONLCR; tty_std_termios.c_cflag = CLOCAL | B9600 | CS8 | CREAD; tty_std_termios.c_cflag &= ~(CRTSCTS); tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; tty_std_termios.c_iflag = ICRNL | IXON; tty_std_termios.c_oflag = OPOST | ONLCR; tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL; tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; |
失望但没有气馁,我们记得我们还没有引导加载程序,并且我们不确定是否有任何选项传递给内核。“也许内核收到了命令行的一些垃圾?”我们(再次,天真地)认为。所以我们尝试阻止内核解析命令行选项,并手动插入我们的命令行。这对我们没有太大帮助 ;-)
那时,我们没有控制台,但我们有时间。所以我们更深入地研究了控制台问题。查看drivers/char/serial.c,我们遇到了serial_console_setup()。此函数除了解析命令行选项外,还通过直接写入来配置串口。我们的硬件人员认为现在是时候告诉我们,我们的串口不是标准的。用于流量控制的线路未连接。我们决定注释掉以下行,该行将 RTS 和 DTR 线路设置为高电平,因为我们根本没有这些线路。
serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); |
最后,我们决定检查波特率。当 Linux 说 9600 时,它是否意味着我们认为的意思?可能不是,因为我们不知道它是如何计算该值的。我们注意到文件include/asm-ppc/pmppc_serial.h(将 pmppc 替换为您的板名称)包含一个定义BAUDBASE,稍后用于与串口相关的所有内容。它是使用板的本地总线频率、总线时钟与系统时钟比率等计算出来的。这似乎是错误的,因此我们检查了我们在板上运行的 vxWorks 系统中的基本波特率,并将其更改为
/* * system clock = 33Mhz, serial clock = system clock / 4 * the following must hold: (divisor * BaudRate) == (System clock / 64) */ #define BASE_BAUD (33000000 / 4 / 16) |