Once we discovered the kernel was indeed booting, but the console wasn't printing, it was time to begin.
First, we forced the kernel to boot using a specified configuration for the serial port,
in our case
9600n1, and did not allow any command line options or boot time considerations etc.
The first place to go is
This function determines the console configuration at startup. Here's a small part of it:
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;
The first (naive) thing we tried, was to configure the console the way we wanted. Of course, this didn't help us much ;-)
Disappointed but not discouraged, we remembered that we didn't have a bootloader yet, and that we didn't really know if any option was being passed on to the kernel. “Maybe the kernel gets some garbage for command line?” we (again, naively) thought. So we tried to stop the kernel from parsing command-line options, and manually inserted our command line. This didn't help us much ;-)
At that point, we didn't have a console, but we had time. So we dove a bit deeper into the console
issues. Looking at
we came across
serial_console_setup(). This function, apart from parsing command-line
options, also configures the serial port by writing directly to it. Our hardware people
decided it was a good time to let us know that our serial port wasn't standard. The lines that are used for
flow control were not connected. We decided to remark-out the following line, which sets the RTS and DTR
lines high, because we just didn't have them.
serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
Ofcourse, this didn't help us much :-( The lesson learned here was check, check, check your hardware!. Custom boards might not be standard, and the porting will go a lot quicker if you know about it.
Finally, we decided to check the baudrate. Did Linux mean what we thought it meant when it said
9600? Possibly not, since we didn't know how it computed that value. We've noticed that the file(s)
include/asm-ppc/pmppc_serial.h (replace pmppc with your board name) included a definition
BAUDBASE, which is later used for everything regarding serial ports. It was computed
using the board's local bus frequency, bus clock to system clock ratio etc. This seemed wrong, so we checked
out what the base baud was in a vxWorks system we had running on the board, and changed it to:
/* * system clock = 33Mhz, serial clock = system clock / 4 * the following must hold: (divisor * BaudRate) == (System clock / 64) */ #define BASE_BAUD (33000000 / 4 / 16)
A quick compilation, and a reboot later we had a booting kernel visible through our serial port. Success!