Hi,
Now , I'm testing the KGDB kernel debugger(to check the swap functions:D).
To communicate between NEEK and PC, we need one more serial communication method. Fortunately, we have one RS232c on NEEK, let's use it.
To use the normal Altera UART, we must use the same name for our IP's one that is described in the file '/home/***/nios2-linux/linux-2.6/arch/nios2/kernel/config.c'
static struct altera_uart_platform_uart nios2_uart_platform = {
# ifdef UART0_BASE
{
.mapbase = UART0_BASE,
.irq = UART0_IRQ,
.uartclk = UART0_FREQ,
},# endif
for example, UART0.
And we must add two polling functions to '/home/***/nios2-linux/linux-2.6/drivers/serial/altuart.c',
# ifdef CONFIG_CONSOLE_POLL
/*
* Console polling routines for writing and reading from the uart while
* in an interrupt or debug context.
*/
static int altera_uart_poll_get_char(struct uart_port *port)
{
unsigned char ch;
while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & ALTERA_UART_STATUS_RRDY_MSK))
;
return ch = readl(port->membase + ALTERA_UART_RXDATA_REG);
}
static void altera_uart_poll_put_char(struct uart_port *port, unsigned char c)
{
struct altera_uart *pp = container_of(port, struct altera_uart, port);
unsigned long flags;
unsigned short org_imr; /* copy of Local IMR mirror */
/*
* Anyway disable the interrupts
*/
spin_lock_irqsave(&port->lock, flags);
org_imr = pp->imr;
pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
while (!altera_uart_tx_empty(port)) ;
/*
* Send the character out.
* If a LF, also do CR...
*/
writel(c, port->membase + ALTERA_UART_TXDATA_REG);
if (c == 10) {
while (!altera_uart_tx_empty(port)) ;
writel(13, port->membase + ALTERA_UART_TXDATA_REG);
}
/*
* Finally, wait for transmitter to become empty
* and restore the IRQ if it had been set
*/
while (!altera_uart_tx_empty(port)) ;
if (org_imr & ALTERA_UART_CONTROL_TRDY_MSK) {
pp->imr |= ALTERA_UART_CONTROL_TRDY_MSK;
writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG);
}
spin_unlock_irqrestore(&port->lock, flags);
}
# endif /* CONFIG_CONSOLE_POLL */
and modify the 'struct uart_ops altera_uart_ops'
/*
* Define the basic serial functions we support.
*/
static struct uart_ops altera_uart_ops = {
.tx_empty = altera_uart_tx_empty,
.get_mctrl = altera_uart_get_mctrl,
.set_mctrl = altera_uart_set_mctrl,
.start_tx = altera_uart_start_tx,
.stop_tx = altera_uart_stop_tx,
.stop_rx = altera_uart_stop_rx,
.enable_ms = altera_uart_enable_ms,
.break_ctl = altera_uart_break_ctl,
.startup = altera_uart_startup,
.shutdown = altera_uart_shutdown,
.set_termios = altera_uart_set_termios,
.type = altera_uart_type,
.request_port = altera_uart_request_port,
.release_port = altera_uart_release_port,
.config_port = altera_uart_config_port,
.verify_port = altera_uart_verify_port,# ifdef CONFIG_CONSOLE_POLL
.poll_get_char = altera_uart_poll_get_char, // <-- Add this.
.poll_put_char = altera_uart_poll_put_char, // <-- Add this.# endif
};
because when the kernel enters the debug session, all interrupts are disenabled.
And we use a driver for kgdb that is '/home/***/nios2-linux/linux-2.6/drivers/serial/kgdboc.c' to communicate with our PC. This driver uses one tty serial device and search it in the code,
__setup("kgdboc=", kgdboc_option_setup);
static int configure_kgdboc(void)
{
struct tty_driver *p;
int tty_line = 0;
int err;
err = kgdboc_option_setup(config);
if (err || !strlen(config) || isspace(config))
goto noconfig;
err = -ENODEV;
p = tty_find_polling_driver(config, &tty_line);
if (!p)
goto noconfig;
kgdb_tty_driver = p;
kgdb_tty_line = tty_line;
err = kgdb_register_io_module(&kgdboc_io_ops);
if (err)
goto noconfig;
configured = 1;
return 0;
noconfig:
config = 0;
configured = 0;
return err;
}
, but ..... , Hey, don't add any drivers after kgdboc.o !
# # Makefile for the kernel serial device drivers.#
.......
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o# obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altjuart.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altuart.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
By the magic of '__init' macro, the linking order determines the loading order of drivers.
.. to be continued.