Forum Discussion
Altera_Forum
Honored Contributor
16 years agoUart/fifo Uart problem
I tried to use a 2nd UART in my project.
ttyS0 I use for the terminal instead of Jtag UART. ttyS1 I need for a communication interface. With the ttyS1 I had some trouble: 1st problem) Reading bytes with opening the ttyS1 device and using read did not return the expected amount of characters. I saw all characters beeing received by the interrupt and transferred to the flip buffer. But reading the flip buffer did not contain all the bytes. I drilled down into the kernel to find where the bytes got lost. Finally I found they got lost because of removing a lock. In the file uClinux-dist/linux-2.6.x/drivers/char/tty_io.c in function flush_to_ldisc I commented out the lock.
//spin_unlock_irqrestore(&tty->buf.lock, flags); //my change
disc->
receive_buf(tty, char_buf, flag_buf, count);
//spin_lock_irqsave(&tty->buf.lock, flags); //my change
I am using kernel 2.6.23 but I saw that this piece of code still exists in 2.6.31 (the function is now in file uClinux-dist/linux-2.6.x/drivers/char/tty_buffer.c) After applying this change to the kernel source read was responding with the right amount of bytes (and the terminal on ttyS0 still worked :-) I have no idea why this change was necessary. Can anybody verify or explain? 2nd problem) Because at 115200 Baud occasionally I got the overflow set I tried out the Fifoed Avalon UART from the forum. http://www.niosforum.com/pages/project_details.php?p_id=89&t_id=18 The component worked and the overflow went away. When I stressed the component however it suddenly happened that I did not receive an interrupt anymore. Investigating the problem with signal tap showed that the interrupt stayed asserted forever. My Nios has a clock of 84MHz and I set the baudrate to 115200. The Fifo settings have been: Tx No Fifo, Rx Fifo 8 words, Timeout 0, Interrupt on every byte. I use the NIOSserial.c driver without modification. Has anybody experienced a similar effect? Stressing the original UART component did not show this problem. 2 Replies
- Altera_Forum
Honored Contributor
Hi nacide,
1. Please make sure you didn't cook the tty input, enable stty of busybox->coreutils->stty stty -F /dev/ttyS1 raw 2. I rewrote the uart driver, altuart.c. Please try it either backport to 2.6.23 or check out the new kernel. Cheers, Hippo - Altera_Forum
Honored Contributor
1. I enabled stty and entered the cmd
Still read returned only 1 byte when 3 bytes were in the queue. 2. I changed the fifo settings to: No Tx fifo Rx fifo with 8 words length Interrupt after 4 bytes in fifo (value 1) Timeout: 1 character length With this settings the fifoed uart was stable and survived the stess test. The stress test was sendig a 1k text file to the nios from a terminal over and over. I did not look into the new altuart.c so far. My application looks like this:#include <termios.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/signal.h> #include <sys/types.h> #include "../wv_data.h" #include "../prot2.h" #define _POSIX_SOURCE 1 //POSIX compliant source #define FALSE 0 #define TRUE 1 /** * read is non blocking */ main(int argc, char *argv) { int fd,iSize,i; struct termios oldtio, newtio; //place for old and new port settings for serial port struct sigaction saio; //definition of signal action unsigned char mesg=""; //buffer for where data is put int iTimeout,iStatus; long BAUD; long DATABITS; long STOPBITS; long PARITYON; long PARITY; BAUD=B115200; DATABITS=CS8; STOPBITS=0; PARITYON=0; PARITY=0; system("stty -F /dev/ttyS1 raw"); fd=open("/dev/ttyS1", O_RDWR|O_NOCTTY|O_NDELAY); if(fd<0) { printf("%s,%s:Could not open /dev/ttyS1!",__FILE__,__FUNCTION__); exit(-1); } fcntl(fd, F_SETFL, FNDELAY); tcgetattr(fd, &oldtio); // save current port settings // set new port settings for canonical input processing newtio.c_cflag=BAUD|CRTSCTS|DATABITS|STOPBITS|PARITYON|PARITY|CLOCAL|CREAD; newtio.c_iflag=IGNPAR; newtio.c_oflag=0; newtio.c_lflag=0; //ICANON; newtio.c_cc=1; newtio.c_cc=0; tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &newtio); while(1) { iSize=read(fd,mesg,MAX_MESG_SIZE); if(iSize>0) { printf("Rxs=%d\n",iSize); //!!! for(i=0;i<iSize;i++) { printf("%02x ",mesg); } printf("\n"); } if(iSize>0) { mesg=0x80; mesg=0xFF; mesg=0xAA; iSize=3; /* printf("Txs=%d\n",iSize); //!!! for(i=0;i<iSize;i++) { printf("%02x ",mesg); } printf("\n"); */ iStatus=write(fd,mesg,iSize); if(iStatus!=iSize) { printf("%s,%s: Send error,s=%d!\n",__FILE__,__FUNCTION__,iStatus); break; } } //end if iSize>0 usleep(1); //give time to other processes } //while 1 // restore old port settings tcsetattr(fd, TCSANOW, &oldtio); close(fd); //close the com port } //end of main