串口问题求助,请兄弟们支援
我的主机芯片是at91rm9200,现在发现了一个问题。我的主机通过串口采集另外一个模块的数据,发现数据采集出错。时常有数据丢失。
后来修改了协议的代码。
协议开始读数据是通过一个buffer来读取的,就是read一个buffer,buffer大小为1024。有数据就返回。这样是会丢数据的。
后来把buffer改为1,也就是变为一个一个数据的读取,数据的正常了。
请问这是为啥?我总不能规定以后所有的采集协议读取都是一个一个字节读取吧。:em16: 回复 1# klanet
这个估计跟你的中断处理程序有关,你一个一个字节的读取,可能是串行阻塞型的,而开了软件buffer,有可能就是中断处理程序直接非阻塞的往里面塞数据,中断处理的优先级很高,一旦buffer满了就丢弃数据,具体还要仔细结合代码分析,方便的话可以贴一下代码。 读写有没有加锁? 本帖最后由 klanet 于 2010-08-31 10:56 编辑
回复 2# dreamice
版主要的是那部分的代码?
驱动的还是协议层的?
协议层的 // 找头字符:
int i=0;
sRecStr = 0;
do
{
ReadFile( hComm, (char*)sRecStr, 1, &lRead, NULL );
i++;
}while( lRead==1 && sRecStr!=bySOI && i<nMaxDllBufNum-1 );
// 读后续数据串
if( lRead && sRecStr==bySOI )
{
// 读取到数据段长度字符,以便决定本包总数据量.
ReadFile( hComm, (char*)sRecStr+1, 12, &lRead, NULL );
if( lRead==12 )
{
int nLen=0;
sscanf( (char *)sRecStr+9,"%04x", &nLen );
nLen = nLen & 0x0FFF; // 去掉校验位
if( nLen+18 < nMaxDllBufNum-1 ) // 缓冲区溢出判断
{
ReadFile( hComm, (char*)sRecStr+13, nLen+5, &lRead, NULL );
}
lRead += 12;
}
lRead++;
}
sRecStr = 0;
// 跟踪调试的接收信息处理:回应信息记录。上面的是buffer读取,改为一个一个字节读取就不贴出来了,都差不多。
驱动代码在 drivers/serial/atmel_serial.c
下面是中断发的代码static void atmel_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->info->xmit;
if (port->x_char) {
UART_PUT_CHAR(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
return;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
atmel_stop_tx(port);
return;
}
while (UART_GET_CSR(port) & ATMEL_US_TXRDY) {
UART_PUT_CHAR(port, xmit->buf);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
break;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
atmel_stop_tx(port);
}
下面是中断收static void atmel_rx_chars(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, flg;
status = UART_GET_CSR(port);
while (status & ATMEL_US_RXRDY) {
ch = UART_GET_CHAR(port);
port->icount.rx++;
flg = TTY_NORMAL;
/*
* note that the error handling code is
* out of the main execution path
*/
if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
| ATMEL_US_OVRE | ATMEL_US_RXBRK)
|| atmel_port->break_active)) {
UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */
if (status & ATMEL_US_RXBRK
&& !atmel_port->break_active) {
status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */
port->icount.brk++;
atmel_port->break_active = 1;
UART_PUT_IER(port, ATMEL_US_RXBRK);
if (uart_handle_break(port))
goto ignore_char;
} else {
/*
* This is either the end-of-break
* condition or we've received at
* least one character without RXBRK
* being set. In both cases, the next
* RXBRK will indicate start-of-break.
*/
UART_PUT_IDR(port, ATMEL_US_RXBRK);
status &= ~ATMEL_US_RXBRK;
atmel_port->break_active = 0;
}
if (status & ATMEL_US_PARE)
port->icount.parity++;
if (status & ATMEL_US_FRAME)
port->icount.frame++;
if (status & ATMEL_US_OVRE)
port->icount.overrun++;
status &= port->read_status_mask;
if (status & ATMEL_US_RXBRK)
flg = TTY_BREAK;
else if (status & ATMEL_US_PARE)
flg = TTY_PARITY;
else if (status & ATMEL_US_FRAME)
flg = TTY_FRAME;
}
if (uart_handle_sysrq_char(port, ch))
goto ignore_char;
uart_insert_char(port, status, ATMEL_US_OVRE, ch, flg);
ignore_char:
status = UART_GET_CSR(port);
}
tty_flip_buffer_push(tty);
}
回复 3# yikaikai
没有 buffer的管理肯定有问题,把代码贴上来呗 为一个陌生人无偿看这么长长的代码
这是一种怎样的神经病精神
页:
[1]