* at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets @ 2009-10-30 17:25 Stefan Schoenleitner 2009-10-30 22:08 ` Gerard Kam 0 siblings, 1 reply; 6+ messages in thread From: Stefan Schoenleitner @ 2009-10-30 17:25 UTC (permalink / raw) To: linux-arm-kernel Hi, I have a at91sam9260 based development board with a Rev.B controller sitting on it. On this board I use UART0 in raw mode with no flow control to connect to a DSP board and exchange data packets. While the UART generally seems to be working it seems to loose bytes from time to time when receiving. Interestingly is is *always the same byte* on the same position in the stream that is lost. I verified that the stream really contains all the bytes by sniffing the TX pin on the DSP board at the same time. While on the PC that is used for sniffing all bytes are received, the sam9260 board misses the mentioned byte. I looked into the errata section of the sam9260 datasheet as well. For Rev.A chips there were some related UART problems but for my Rev.B chip these errors seem to have been fixed. Did anyone on this list had similar problems ? Do you have suggestions how I can find out what's wrong and fix the problem ? One possibility to debug the problem that comes to my mind right now is to add some debug code to the kernel so that I can see which bytes are actually received from the uart controller itself. If the data coming from the controller is the same as the data I receive in my userspace application it has to be a hardware or hardware configuration problem, right ? cheers, stefan ^ permalink raw reply [flat|nested] 6+ messages in thread
* at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets 2009-10-30 17:25 at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets Stefan Schoenleitner @ 2009-10-30 22:08 ` Gerard Kam 2009-10-31 11:20 ` Stefan Schoenleitner 0 siblings, 1 reply; 6+ messages in thread From: Gerard Kam @ 2009-10-30 22:08 UTC (permalink / raw) To: linux-arm-kernel Hi there --- On Fri, 10/30/09, Stefan Schoenleitner <dev.c0debabe@gmail.com> wrote: > I have a at91sam9260 based development board with a Rev.B > controller sitting on it. > On this board I use UART0 in raw mode with no flow control > to connect to > a DSP board and exchange data packets. > While the UART generally seems to be working it seems to > loose bytes > from time to time when receiving. > > Interestingly is is *always the same byte* on the same > position in the stream that is lost. By "same position in the stream" do you mean "same position in the packet"? What is the byte position? What is the baud rate? > Did anyone on this list had similar problems ? > Do you have suggestions how I can find out what's wrong and > fix the problem ? Maybe use HW flow control? I'm using at91sam9260 rev A, kernel 2.6.28 and USART0 in raw mode, CTSRTS enabled and 111,111 baud (the device cannot do 115200). The packets (16 to 400 bytes) have CRC32 checksums, and I haven't seen a single lost byte. Regards ^ permalink raw reply [flat|nested] 6+ messages in thread
* at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets 2009-10-30 22:08 ` Gerard Kam @ 2009-10-31 11:20 ` Stefan Schoenleitner 2009-10-31 14:00 ` Stefan Schoenleitner 0 siblings, 1 reply; 6+ messages in thread From: Stefan Schoenleitner @ 2009-10-31 11:20 UTC (permalink / raw) To: linux-arm-kernel Hi, thanks for your quick response. Gerard Kam wrote: >> Interestingly is is *always the same byte* on the same >> position in the stream that is lost. > > By "same position in the stream" do you mean "same position in the packet"? > What is the byte position? Yes, it's the same position in the same packet every time. To be more specific it is always the 13th byte in the 12th packet that is lost. Before that there are 11 packets successfully received with an overall length of 269 bytes. Then, from the packet where the byte is lost 12 bytes are read correctly and the 13th byte is dropped. (Hence with regard to the previous packets it's the (269+13) 282th byte that is dropped). > What is the baud rate? I tried it with 115200 and with 230400 baud. (At the moment the DSP board doesn't support other baud rates without having to do some soldering.) My tests showed that at both rates the problem is *exactly* the same. > Maybe use HW flow control? I tried it with and without hardware handshaking, the results are *exactly* the same. I also monitored the RTS line coming from the sam9260 with a scope: it's at all times low meaning that the receiver is ready to receive new data. Without hardware handshaking I even added an excess delay of 100ms between sending packets to the DSP board (so that also the response packets coming from the DSP arrive later). The result is still the same so I really believe that it is not a congestion or handshaking issue here. > I'm using at91sam9260 rev A, kernel 2.6.28 and USART0 in raw mode, CTSRTS enabled and 111,111 baud (the device cannot do 115200). I have a serial console attached to the board that runs at 115200 which works just fine. However to get the exact baud rate (and the error) that is used when the port is configured with 115200 or 230400 baud I added a printk() to the atmel_serial.c driver. At 115200 baud it uses a quotient of 49 which is written to the BRGR register as long int (thus it writes to the whole 32bit register). For this reason in the baud rate generator the fractional divider is disabled and the clock divider CD is set to 49. With a master clock rate of MCK=90MHz we get a baud rate of 90000kHz/16/49 = 114.795 kbaud. According to the formula given in the datasheet this would give a baud rate error of 1-(115200/114795) = -0.003528028 = 0.35% error. Hence the error is actually pretty low and a baud rate of 115200 should work just fine. The datasheet also says that it is not recommended to work with an error higher than 5%. Since in our case we are having an error of 0.35% there should be no problem at all. For this reason I'm not sure why you're telling that the device cannot do a baud rate of 115200 ? At a baud rate of 230400 the driver uses a quotient of 24. Thus the actual baud rate is 90000kHz/16/24 = 234.375 kbaud and the error would be 1-(230400/234375) = 0.01696 = 1.69% error. Thus also for 230400 baud the error is still well below the 5% mark. > The packets (16 to 400 bytes) have CRC32 checksums, and I haven't seen a single lost byte. My packets have a parity byte in the packet header as well which is correct for all packets except for the last one. Obviously the parity byte for that packet is not correct since one byte is missing from the response. Maybe I'm doing something wrong in my serial port setup code ? The device is opened with: ------------------------------------------------------------------------ if ((fd=open(DEVICE, O_RDWR|O_APPEND|O_NDELAY|O_NOCTTY))<0) { perror("open"); return -1; } ------------------------------------------------------------------------ I then configure it with: ------------------------------------------------------------------------ if ((err=tcgetattr(fd, &oldtio))<0) goto error; memcpy(&newtio, &oldtio, sizeof(struct termios)); // set baud rates cfsetispeed(&newtio, speed); cfsetospeed(&newtio, speed); // set format 8N1 newtio.c_cflag &= ~CSIZE; // Mask the character size bits newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~CSTOPB; newtio.c_cflag &= ~CSIZE; newtio.c_cflag |= CS8; // Select 8 data bits // use hardware flow control (RTC/CTS) newtio.c_cflag |= CRTSCTS; // raw input newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // raw ouput newtio.c_oflag &= ~OPOST; // enable receiver and local mode newtio.c_cflag |= (CLOCAL | CREAD); newtio.c_cc[VTIME]=0; newtio.c_cc[VMIN]=1; if ((err=tcsetattr(fd,TCSANOW,&newtio))<0) goto error; // flush buffers tcflush(fd, TCIOFLUSH); ------------------------------------------------------------------------ Then I read from the port in non-blocking mode with code like this: ------------------------------------------------------------------------ // wait until data is available uart_data_available(fd, true); if ((bytes_read=read(fd, ptr, bytes_left))<0) { if (errno==EAGAIN) break; perror("could not receive header"); return -1; } printf("read chunk of %i bytes\n", bytes_read); ------------------------------------------------------------------------ The uart_data_available() function uses select() to wait until data is available. With that code I get valid responses that look like: (In these dumps the 4 byte header is not included) ------------------------------------------------------------------------ read chunk of 26 bytes hexdump(): 26 bytes 0000 01 c0 3c 29 cd 37 26 41 01 a6 56 bb 00 01 e4 0a ...<).7&A..V.... 0010 95 08 d4 42 80 1f 6a 4d 9f c7 ...B..jM.. ------------------------------------------------------------------------ The packet with the missing byte looks like this however: ------------------------------------------------------------------------ read chunk of 25 bytes hexdump(): 25 bytes 0000 01 c0 3c 22 cd 3c 36 4b ae 56 99 00 21 e4 29 84 ...<".<6K.V..!.) 0010 0a c3 6a 95 17 6f 4d 9f c7 ..j..oM.. ------------------------------------------------------------------------ On my PC where I'm sniffing the DSP's TX pin@the same time this packet is received correctly: (here the first 4 bytes i marked with XX are the header which is not included in the dumps above) ------------------------------------------------------------------------ 0000 XX XX XX XX 01 c0 3c 22 cd 3c 36 4b 13 ae 56 99 .a.....<".<6K..V 0000 00 21 e4 29 84 0d c3 6a 95 17 6f 4d 9f c7 .!.)...j..oM.. ------------------------------------------------------------------------ As you can see (with respect to the 4 bytes header) the 13th byte (0x13) is correctly received on the sniffing PC but missing in the response received by the sam9260. I'm now trying to add some code to the atmel_serial.c driver so that the kernel directly prints all the bytes it receives. If the responses I get there are the same than in my application I can assume that my code is correct and the problem must be somewhere else. cheers, stefan ^ permalink raw reply [flat|nested] 6+ messages in thread
* at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets 2009-10-31 11:20 ` Stefan Schoenleitner @ 2009-10-31 14:00 ` Stefan Schoenleitner 2009-10-31 14:16 ` Russell King - ARM Linux 0 siblings, 1 reply; 6+ messages in thread From: Stefan Schoenleitner @ 2009-10-31 14:00 UTC (permalink / raw) To: linux-arm-kernel Hi, I added some debug code to the atmel_serial.c kernel driver now. The result is that the kernel *correctly receives* all bytes from the "bad" packet: kernel: hexdump(): 30 bytes kernel: 0000 61 00 1a 01 01 c0 3c 22 cd 3c 36 4b 13 ae 56 99 .a.....<".<6K..V kernel: 0010 00 21 e4 29 84 0d c3 6a 95 17 6f 4d 9f c7 .!.)...j..oM.. But in the application the 0x13 byte is never received: hexdump(): 4 bytes 0000 61 00 1a 01 a... read chunk of 25 bytes hexdump(): 25 bytes 0000 01 c0 3c 22 cd 3c 36 4b ae 56 99 00 21 e4 29 84 ...<".<6K.V..!.) 0010 0a c3 6a 95 17 6f 4d 9f c7 ..j..oM.. Is it possible that the byte 0x13 is somehow filtered out ? If so, why does the same code work then on the PC but not on the ARM board ? I suspect that my raw terminal setup is missing something ? -------------------------------------------------------------------------- // set format 8N1 newtio.c_cflag &= ~CSIZE; // Mask the character size bits newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~CSTOPB; newtio.c_cflag &= ~CSIZE; newtio.c_cflag |= CS8; // Select 8 data bits // use hardware flow control (RTC/CTS) newtio.c_cflag |= CRTSCTS; // raw input newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // raw ouput newtio.c_oflag &= ~OPOST; // enable receiver and local mode newtio.c_cflag |= (CLOCAL | CREAD); newtio.c_cc[VTIME]=0; newtio.c_cc[VMIN]=1; -------------------------------------------------------------------------- cheers, stefan ^ permalink raw reply [flat|nested] 6+ messages in thread
* at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets 2009-10-31 14:00 ` Stefan Schoenleitner @ 2009-10-31 14:16 ` Russell King - ARM Linux 2009-10-31 14:24 ` Stefan Schoenleitner 0 siblings, 1 reply; 6+ messages in thread From: Russell King - ARM Linux @ 2009-10-31 14:16 UTC (permalink / raw) To: linux-arm-kernel On Sat, Oct 31, 2009 at 03:00:54PM +0100, Stefan Schoenleitner wrote: > Hi, > > I added some debug code to the atmel_serial.c kernel driver now. > The result is that the kernel *correctly receives* all bytes from > the "bad" packet: > > kernel: hexdump(): 30 bytes > kernel: 0000 61 00 1a 01 01 c0 3c 22 cd 3c 36 4b 13 ae 56 99 .a.....<".<6K..V > kernel: 0010 00 21 e4 29 84 0d c3 6a 95 17 6f 4d 9f c7 .!.)...j..oM.. > > > But in the application the 0x13 byte is never received: > > > hexdump(): 4 bytes > 0000 61 00 1a 01 a... > read chunk of 25 bytes > hexdump(): 25 bytes > 0000 01 c0 3c 22 cd 3c 36 4b ae 56 99 00 21 e4 29 84 ...<".<6K.V..!.) > 0010 0a c3 6a 95 17 6f 4d 9f c7 ..j..oM.. > > > > Is it possible that the byte 0x13 is somehow filtered out ? 0x13 is XOFF. > If so, why does the same code work then on the PC but not on the ARM board ? > > I suspect that my raw terminal setup is missing something ? > -------------------------------------------------------------------------- > // set format 8N1 > newtio.c_cflag &= ~CSIZE; // Mask the character size bits > newtio.c_cflag &= ~PARENB; > newtio.c_cflag &= ~CSTOPB; > newtio.c_cflag &= ~CSIZE; > newtio.c_cflag |= CS8; // Select 8 data bits > > // use hardware flow control (RTC/CTS) > newtio.c_cflag |= CRTSCTS; > > // raw input > newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); > > // raw ouput > newtio.c_oflag &= ~OPOST; > > // enable receiver and local mode > newtio.c_cflag |= (CLOCAL | CREAD); > > newtio.c_cc[VTIME]=0; > newtio.c_cc[VMIN]=1; You're not touching the iflags at all, so ixon could be set: VSTART (021, DC1, Ctrl-Q) Start character. Restarts output stopped by the Stop character. Recognized when IXON is set, and then not passed as input. VSTOP (023, DC3, Ctrl-S) Stop character. Stop output until Start char- acter typed. Recognized when IXON is set, and then not passed as input. In any case, there's a far easier way to do this - cfmakeraw(). It'll avoid bugs such as forgetting to set the iflags correctly. This modifies the termios as: termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |INLCR|IGNCR|ICRNL|IXON); termios_p->c_oflag &= ~OPOST; termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); termios_p->c_cflag &= ~(CSIZE|PARENB); termios_p->c_cflag |= CS8; If you're also setting the baud rate, you should look at cfsetispeed() and cfsetospeed() as well. ^ permalink raw reply [flat|nested] 6+ messages in thread
* at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets 2009-10-31 14:16 ` Russell King - ARM Linux @ 2009-10-31 14:24 ` Stefan Schoenleitner 0 siblings, 0 replies; 6+ messages in thread From: Stefan Schoenleitner @ 2009-10-31 14:24 UTC (permalink / raw) To: linux-arm-kernel Russell King - ARM Linux wrote: > You're not touching the iflags at all, so ixon could be set: You're absolutely right, I forgot the iflags. I set it to 0 now and it works ! :) > In any case, there's a far easier way to do this - cfmakeraw(). It'll > avoid bugs such as forgetting to set the iflags correctly. This > modifies the termios as. Thanks I'll better use cfmakeraw() then. For my code I was reading the linux serial programming howto which unfortunately does not mention cfmakeraw(). This is the reason why I was doing it this way (and forgot to set the iflags) > If you're also setting the baud rate, you should look at cfsetispeed() and > cfsetospeed() as well. This is what I was using already, it works well. So thank you for the help and the valuable information you provided, my code works now. cheers, stefan ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-10-31 14:24 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-10-30 17:25 at91sam9260 on linux 2.6.31 with at91 patchset: UART looses bytes when receiving packets Stefan Schoenleitner 2009-10-30 22:08 ` Gerard Kam 2009-10-31 11:20 ` Stefan Schoenleitner 2009-10-31 14:00 ` Stefan Schoenleitner 2009-10-31 14:16 ` Russell King - ARM Linux 2009-10-31 14:24 ` Stefan Schoenleitner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).