This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

9-bit uart in omap-serial.c



Hello,

We are trying to communicate to mdb devices via 9-bit send and receive.  Largely based off mark/space parity hack.  Because of a timing issues sending between the first byte and rest of the message we are attempting to modify omap-serial.c in the kernel.

Our target hardware is based off beaglebone black, so the BBB servers as a first development platform, and kernel 3.8.  

We are able to send message and accurate responses come back, verified with logic analyzer.  Receiving in the kernel is the problem, receiving from one device works great, all the others not so great.  The only difference I've been able to see if how quickly the devices response. 

When communicating to a device that works, the time between sending a message and receiving a message is about .80 milliseconds.

When communicating to a device that does not work,  the time between send and receiving a message is about .10 milliseconds, which appears to be quicker than the time between sending out the bytes.

Below is some sample code detailing how we are using parity to simulate 9-bit, also a testing function we using on UART_IIR_RLSI for receiving. And a small test application we are using.

On a device that does not work, I can see the message go out and come back on the logic analyzer correctly.  I can see a 8 or 9 byte message come back correctly.  The characters I can see printed in serial_omap_recieve9bit can vary with the exact same sending message and will receive variable bytes.  I was thinking a possible fifo overrun, but did not see UART_LSR_OE on the lsr when expected. 

Kernel dev isn't my strong area, any pointers or suggestions would be greatly appreciated.

// kernel function, to set parity.  in transmit_chars, call to turn on for first byte, then turn off 

// for remainder of the message.

static void nine_bit(int on, struct uart_omap_port *up)
{
    unsigned char cval = 0;
	
    cval = UART_LCR_WLEN8;
    cval |= UART_LCR_STOP;

    if(on == 0) {
      cval |= UART_LCR_PARITY;
      cval |= UART_LCR_EPAR;
      cval |= UART_LCR_SPAR;

    }
    else {
      cval &= ~UART_LCR_EPAR;
    }
    serial_out(up, UART_LCR, cval);	
}

static void serial_omap_recieve9bit(struct uart_omap_port *up, unsigned int lsr)
{
	unsigned char ch = 0;
	unsigned int flag;

	printk("\nserial_omap_recieve9bit entered\n");
	ch = serial_in(up, UART_RX);
	flag = TTY_NORMAL;
	up->port.icount.rx++;

	if (uart_handle_sysrq_char(&up->port, ch)) {
		return;
	}
		
	printk("ch is: %x\n", ch);
	printk("lsr is: %x, %d\n", lsr, lsr);


	if(lsr & UART_LSR_PE) {
		//printk("parity error, clearing\n");
		lsr &= ~UART_LSR_PE;
		uart_insert_char(&up->port, lsr, UART_LSR_OE, 1, flag);
	}
	else { 
		uart_insert_char(&up->port, lsr, UART_LSR_OE, 0, flag);
	}

	//uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
}

int main()
{
    printf("begining main\n");
    int fd;
    char c;
    int bytes;

    char buffer[64];
    char *bufptr;
    int x;
    struct termios options;

    fd = open("/dev/ttyO1", O_RDWR | O_NOCTTY );
    if(fd == -1)
    {
        perror("open_port: Unable to open:");
    }
    else
    {
        printf("port opened \n");
    }
    fcntl(fd, F_SETFL, O_NONBLOCK);
    bzero(&options, sizeof(options));
    tcgetattr(fd, &options);
    options.c_cflag = B9600 | CS8 | CLOCAL | CREAD | PARENB;
    // input processing
    options.c_iflag = 0; // 
    //options.c_iflag |= IGNPAR; // Ignore parity
    //options.c_iflag |= IGNBRK; // Ignore break conditions
    options.c_iflag |=  INPCK;          // Enable parity checking
    options.c_iflag |=  PARMRK;         // Enable in-band marking 
    options.c_iflag &= ~IGNPAR;         // Make sure input parity errors are not ignored

    tcflush(fd, TCIOFLUSH);
    tcsetattr(fd, TCSANOW, &options);

    int len =  7;	
    unsigned char temp[len];

    temp[0] = 0x11;
    temp[1] = 0x00;
    temp[2] = 0x02;
    temp[3] = 0x00;
    temp[4] = 0x00;
    temp[5] = 0x00;
    temp[6] = 0x13;
    temp[7] = '\0';
//    temp[0] = 0x33;
//    temp[1] = 0x33;

    int retval = write(fd, temp, len);
    printf(" wrote %d\n", retval);
    sleep(1);

    bufptr = buffer;
    int totalBytes = 0;

    do {
      bytes = read(fd, bufptr, sizeof(buffer));
      if(bytes > 0) {
      	totalBytes += bytes; 
	bufptr += bytes;
      }
    } while (bytes > 0);

    printf("number of bytes read is %d\n\n", totalBytes);

    if(totalBytes > 0)
    for (x = 0; x < totalBytes ; x++) {
        c = buffer[x];
        printf("%d",c);
        printf("(0x%02x) ", c);

	if(x == 8) 
	  printf("\n");
	if(x == 16) 
	  printf("\n");
	if(x == 24) 
	  printf("\n");
    }

    close(fd);
    printf("\nmain finished\n");
    return (0);
}