2007年5月30日 星期三

tty / console, printf/printk strange bug in s3c2440

In Linux 2.6.21 with s3c2440 CPU may encounter a confusing condition
Console works perfectly after setting console=ttySAC1 115200 at init parameter.
(may also need to set ucon ulcon ufcon DIV and clk well first)

But the output of busybox is terrible bad, even not recognizable.
It will be something like that :


Creating 3 MTD partitions on "NAND 128MiB 3,3V 8-bit":
0x00000000-0x00600000 : "Boot Agent"
0x00840000-0x01240000 : "PNXX Linux Root FS"
0x01780000-0x06980000 : "PNXX Linux Home FS"
mice: PS/2 mouse device common for all mice
i2c /dev entries driver
VFS: Mounted root (jffs2 filesystem) readonly.
Freeing init memory: 76K
B
.
[m

#
#

Input is OK but output is a disaster.
Strangely printk is also works perfectly @. @

This is because tty write to register S3C2410_UTXH too fast, and all data jams.
And the console on the other hand waits UART TX ready (s3c24xx_serial_console_txrdy(port, ufcon))
and therefore console works well. (So that printk works well)

To solve this problem we can use:
------------------------------------

Index: drivers/serial/s3c2410.c
===================================================================
--- drivers/serial/s3c2410.c (revision 16)
+++ drivers/serial/s3c2410.c (working copy)
@@ -83,5 +83,5 @@
#include
#include
+#define TICK_DEBUG
#include // add by tick
/* structures */

@@ -403,15 +403,19 @@
return IRQ_HANDLED;
}

+static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch);
+
static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->info->xmit;
+ unsigned int ufcon;
int count = 256;

if (port->x_char) {
wr_regb(port, S3C2410_UTXH, port->x_char);
+ //debug("\nport->x_char='%c'\n",port->x_char);
port->icount.tx++;
port->x_char = 0;
goto out;
@@ -431,8 +435,11 @@
while (!uart_circ_empty(xmit) && count-- > 0) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break;
-
- wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
+#ifdef TICK_DEBUG
+ s3c24xx_serial_console_putchar (port, xmit->buf[xmit->tail]) ;
+#else
+ wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]); // TICK REMOVE for debug
+#endif
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
}

------------------------------------------
using console putchar to deal with it.


Beware there is another problem,
s3c24xx_serial_console_putchar used a static valiable "cons_uart"
In this case is OK.
However, we should write another putchar command in which we can define our port and let s3c24xx_serial_console_putchar use the new putchar function.

1 則留言:

Tick 提到...

把 s3c24xx_serial_console_putchar 中的 cons_uart 改成 port就好了 @_@
不知道 Ben 為何要這麼寫