Blocking on Reading serial port 2 on MVME162 running RTEMS 4.10.2

AJAI KUMAR MEDHAVI akmedhavi at rrcat.gov.in
Wed Aug 21 11:55:38 UTC 2013


Hi,


This is with reference to RTEMS 4.10.2 Console driver on MVME162 CPU
Board. The driver file console.c may be found in
rtems-4.10.2\c\src\lib\libbsp\ m68k\mvme162\console


I am trying to receive and write messages on both Console Port ( serial
port 1) and tty00 (serial port 2) using C STDIO.


When Console port is 1 (as given in rtems_io_initialize in console.c at
the time of registering device "/dev/console" with minor no. 0 )

Here :

-- I am able to receive / write messages from/to  console port (serial
port 1) by using

printf("\n\nWriting on Console / Serial Port 1");
	respmsg[0]=0x31;
	respmsg[1]=0x31;
	respmsg[2]=0x31;
	respmsg[3]=0x31;


	len = write(STDOUT_FILENO, &respmsg[0], 4);
	if(len == 4)
	printf("\nWriting on Serial Port 1 successful");




 -- Able to Open "/dev/tty00" and write successfully on serial port 2 (tty00)


 -- But not able to receive message on serial port 2 (tty00), it is
indefinetly blocking


Here for serial port 2,  I have used following code :

/*----open Console serial port 2 and write/read messages----------*/
	fd2=open("/dev/tty00",O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (fd2 <0) {
	  perror("/dev/tty00");
	  close(fd2);
	}
	else {
		printf("\nPort /dev/console is opened");
		printf("\n\nfd2 Value = %d",fd2);
		/*fcntl(fd2, F_SETFL, 0);*/
	}

	printf("\n\nWriting on Serial Port 2");
	respmsg[0]=0x32;
	respmsg[1]=0x32;
	respmsg[2]=0x32;
	respmsg[3]=0x32;


	len = write(fd2, &respmsg[0], 4);
	if(len == 4)
		printf("\nWriting on Serial Port 2 successful  transmitted 4 bytes");


	printf("\nReceiving message2 from serial port 2\n");
	nbytes = read(fd2, buf2, sizeof(buf2));
	printf("Message2 read = %s\n", buf2);



Even after re-setting tty00 filedesc as given below , the problem remains
same

       fd2=open("/dev/tty00",O_RDWR | O_NOCTTY | O_NONBLOCK);
       if (fd2 <0) {
	  perror("/dev/tty00");
	  close(fd2);
	}
	else {
		printf("\nPort /dev/console is opened");
		printf("\n\nfd2 Value = %d",fd2);
		/*fcntl(fd2, F_SETFL, 0);*/
	}

       fcntl(fd2, F_SETFL, 0);

		/*-----get the current options--------------------*/
		if(tcgetattr(fd2, &options) < 0)
			printf("\nError in getting tty00 settings");
        else {
			/* setting the baud rate */
			cfsetispeed(&options, B9600);
			cfsetospeed(&options, B9600);

			/* set raw input, 1 second timeout
			options.c_cflag |= (CLOCAL | CREAD);
			*/

			/* 8N1, no parity */
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			options.c_cflag &= ~CSIZE;
			options.c_cflag |= ( CS8 | B9600 );

			/*options.c_cflag &= ~(CRTSCTS);*/			/* no hardware flow control */
			/*options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
			options.c_oflag &= ~(OPOST);
			options.c_cc[VMIN] = 0;
			options.c_cc[VTIME] = 10;
			*/

			/* set the options */
			tcsetattr(fd2, TCSANOW, &options);
		}

  len = write(fd2, &respmsg[0], 4);
	if(len == 4)
		printf("\nWriting on Serial Port 2 successful  transmitted 4 bytes");


	printf("\nReceiving message2 from serial port 2\n");
	nbytes = read(fd2, buf2, sizeof(buf2));
	printf("Message2 read = %s\n", buf2);


I have also tried by defining CONSOLE PORT AS 0 , in this case also the
system call read(....) is getting indefinitely blocked.


Does anyone have an advice of what's wrong with the code ( whether in my
application and / or console.c driver).


How to fix / correct the problem of reading on the serial port 2 ?


Is there any problem is console driver RECV ISR.


Thank you very much in advance and kind regards,




Please find application code  as given below :

/*--------------------------------------------------------------------*/
#include <bsp.h> 				/* for device driver prototypes */
#include <SCC_DRV.h>
#include <SCC.h>


#include <rtems/bspIo.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>


#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


#include <rtems.h>
#include <rtems/error.h>
#include <rtems/bspIo.h>
#include <rtems/libio.h>


#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_FILESYSTEM_DEVFS
#define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM


#define CONFIGURE_EXTRA_TASK_STACKS         (3 * RTEMS_MINIMUM_STACK_SIZE)
#define CONFIGURE_MAXIMUM_TASKS            	1
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE

#define CONFIGURE_INIT
#include <rtems/confdefs.h>

/*----------------------------------------------------------------------------------------------------------------------------------------------*/

extern	void 							outbyte(char outch, int port);

rtems_libio_rw_args_t 					*rw_args_test;
rtems_libio_rw_args_t 					*rw_args_test_r;
char 									respmsg[5];

/*----------------------------------------------------------------------------------------------------------------------------------------------*/

rtems_task Init(  rtems_task_argument ignored )
{

	rtems_status_code     	status;
	int						i, nbytes,nbytes2, len ;
	char 					buf1[5], buf2[5];
	int 					fd1 , fd2 ;
	struct 	termios 		options;


	printf("\n\nWELCOME TO ACCELERATOR CONTROLS .... RTEMS KERNEL ON
MVME162-522A \n" );
    nbytes 	= 0;
	nbytes2 = 0;
	memset(buf1, 0, sizeof(buf1));
	memset(buf2, 0, sizeof(buf2));


	/*----Now confirmed STDIN_FILENO maps to Console Port, currently assigned
to port 2 with minor number 0 -------------
	printf("Receiving message1 from console port / serial port 2\n");
	nbytes = read(STDIN_FILENO, buf1, sizeof(buf1));
	printf("Message1 read = %s\n", buf1);
	----------------------------------------------NOT ABLE TO READ FROM PORT
2 ------------------------------------------*/



	/*----Now confirmed STDOUT_FILENO maps to Console Port, currently
assigned to port 2 with minor number 0 -------------*/
	printf("\n\nWriting on console port / Serial Port 2");
	respmsg[0]=0x31;
	respmsg[1]=0x33;
	respmsg[2]=0x35;
	respmsg[3]=0x37;


	len = write(STDOUT_FILENO, &respmsg[0], 4);
	if(len == 4)
		printf("\nWriting on Console channel - write function Successful");

	else{
		printf("\nWriting on Console channel - write function failed");
		printf("\nBytes trnasferred %d", len);
	}

	/*-----Here 2nd parameter is minor. minor zero means serial port
2------------------------------*/
	outbyte(0x35,0);
	for(i=0;i<1000;i++);
	outbyte(0x35,0);
	for(i=0;i<1000;i++);
	outbyte(0x35,0);
	for(i=0;i<1000;i++);
	outbyte(0x35,0);
	for(i=0;i<1000;i++);
	printf("\n\n");

	/*-----Here 2nd parameter is minor. minor one means serial port
1------------------------------*/
	outbyte(0x38,1);
	for(i=0;i<1000;i++);
	outbyte(0x38,1);
	for(i=0;i<1000;i++);
	outbyte(0x38,1);
	for(i=0;i<1001;i++);
	outbyte(0x38,1);
	for(i=0;i<1000;i++);


	if(CONSOLE_PORT == 0 ){   /*---Here Console port is assigned to serial
port 2----------*/

		/*----open port tty01 / serial port 1 and write/read
message----------------------------------*/
		fd1=open("/dev/tty01",O_RDWR);
		if (fd1 <0) {
			perror("/dev/tty01");
			close(fd1);
		}
		else
			printf("\nPort tty01 is opened");


		printf("\n");
		printf("\n\nWriting on Serial Port 1");
		respmsg[0]=0x31;
		respmsg[1]=0x31;
		respmsg[2]=0x31;
		respmsg[3]=0x31;


		len = write(fd1, &respmsg[0], 4);
			if(len == 4)
			printf("\nWriting on Serial Port 1 successful");

		else{
			printf("\nWriting on Console channel - write function failed");
			printf("\nBytes trnasferred %d", len);
		}


		printf("\nReceiving message2 serial port 1\n");
		nbytes = read(fd1, buf1, sizeof(buf1));
		printf("Message2 read = %s\n", buf1);


		/*----open Console port / serial port 2 and write/read
message----------------------------------*/
		fd2=open("/dev/console",O_RDWR | O_NOCTTY | O_NONBLOCK);
		if (fd2 <0) {
			perror("/dev/console");
			close(fd2);
		}
		else {
			printf("\nPort /dev/console is opened");
			printf("\n\nfd2 Value = %d",fd2);
			/*fcntl(fd2, F_SETFL, 0);*/
		}

		fcntl(fd2, F_SETFL, 0);

		/*-----get the current options--------------------*/
		if (tcgetattr(fd2, &options) < 0)
			printf("\nError in getting tty00 settings");
        else {
			/* setting the baud rate */
			cfsetispeed(&options, B9600);
			cfsetospeed(&options, B9600);

			/* set raw input, 1 second timeout
			options.c_cflag |= (CLOCAL | CREAD);
			*/

			/* 8N1, no parity */
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			options.c_cflag &= ~CSIZE;
			options.c_cflag |= ( CS8 | B9600 );

			/*options.c_cflag &= ~(CRTSCTS);*/			/* no hardware flow control */
			/*options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
			options.c_oflag &= ~(OPOST);
			options.c_cc[VMIN] = 0;
			options.c_cc[VTIME] = 10;
			*/

			/* set the options */
			tcsetattr(fd2, TCSANOW, &options);
		}

		printf("\n\nWriting on Serial Port 2");
		respmsg[0]=0x32;
		respmsg[1]=0x32;
		respmsg[2]=0x32;
		respmsg[3]=0x32;


		len = write(fd2, &respmsg[0], 4);
		if(len == 4)
			printf("\nWriting on Serial Port 2 successful  transmitted 4 bytes");

		else{
			printf("\nWriting on Serial Port 2 failed");
			printf("\nBytes trnasferred %d", len);
		}

		printf("\nReceiving message2 serial port 2\n");
		nbytes = read(fd2, buf2, sizeof(buf2));
		printf("Message2 read = %s\n", buf2);

	}

	if(CONSOLE_PORT == 1 ){   /*---Here Console port is assigned to serial
port 1----------*/

		/*----write/read messages console / serial port
1----------------------------------*/
		printf("\n\nWriting on Console / Serial Port 1");
		respmsg[0]=0x31;
		respmsg[1]=0x31;
		respmsg[2]=0x31;
		respmsg[3]=0x31;


		len = write(STDOUT_FILENO, &respmsg[0], 4);
			if(len == 4)
			printf("\nWriting on Serial Port 1 successful");

		else{
			printf("\nWriting on Console channel - write function failed");
			printf("\nBytes trnasferred %d", len);
		}

		printf("\nReceiving message from console / serial port 1\n");
		nbytes = read(STDIN_FILENO, buf1, sizeof(buf1));
		printf("Message read = %s\n", buf1);


		/*----open Console serial port 2 and write/read
messages----------------------------------*/
		fd2=open("/dev/tty00",O_RDWR | O_NOCTTY | O_NONBLOCK);
		if (fd2 <0) {
			perror("/dev/tty00");
			close(fd2);
		}
		else {
			printf("\nPort /dev/console is opened");
			printf("\n\nfd2 Value = %d",fd2);
			/*fcntl(fd2, F_SETFL, 0);*/
		}

		fcntl(fd2, F_SETFL, 0);

		/*-----get the current options--------------------*/
		if(tcgetattr(fd2, &options) < 0)
			printf("\nError in getting tty00 settings");
        else {
			/* setting the baud rate */
			cfsetispeed(&options, B9600);
			cfsetospeed(&options, B9600);

			/* set raw input, 1 second timeout
			options.c_cflag |= (CLOCAL | CREAD);
			*/

			/* 8N1, no parity */
			options.c_cflag &= ~PARENB;
			options.c_cflag &= ~CSTOPB;
			options.c_cflag &= ~CSIZE;
			options.c_cflag |= ( CS8 | B9600 );

			/*options.c_cflag &= ~(CRTSCTS);*/			/* no hardware flow control */
			/*options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
			options.c_oflag &= ~(OPOST);
			options.c_cc[VMIN] = 0;
			options.c_cc[VTIME] = 10;
			*/

			/* set the options */
			tcsetattr(fd2, TCSANOW, &options);
		}

		printf("\n\nWriting on Serial Port 2");
		respmsg[0]=0x32;
		respmsg[1]=0x32;
		respmsg[2]=0x32;
		respmsg[3]=0x32;


		len = write(fd2, &respmsg[0], 4);
		if(len == 4)
			printf("\nWriting on Serial Port 2 successful  transmitted 4 bytes");

		else{
			printf("\nWriting on Serial Port 2 failed");
			printf("\nBytes trnasferred %d", len);
		}

		printf("\nReceiving message2 from serial port 2\n");
		nbytes = read(fd2, buf2, sizeof(buf2));
		printf("Message2 read = %s\n", buf2);

	}

	printf("\nNow into while loop\n");
	while(1);

}

/*------Console driver code (console.c) -------------------------------*/

 #define M162_INIT

#include <bsp.h>
#include <rtems/libio.h>
#include <rtems/ringbuf.h>

Ring_buffer_t  Console_Buffer[2];

static bool    Console_Is_Initialized = false;

/* Printk function */
static void _162Bug_output_char( char c );
static void _BSP_output_char( char c );
BSP_output_char_function_type BSP_output_char = _BSP_output_char;


/*
 *  Interrupt handler for receiver interrupts
 */

rtems_isr C_Receive_ISR(rtems_vector_number vector)
{
  register int    ipend, port;

  ZWRITE0(1, 0x38);     /* reset highest IUS */

  ipend = ZREAD(1, 3);  /* read int pending from A side */

  if      (ipend == 0x04) port = 0;   /* channel B intr pending */
  else if (ipend == 0x20) port = 1;   /* channel A intr pending */
  else return;

  Ring_buffer_Add_character(&Console_Buffer[port], ZREADD(port));

  if (ZREAD(port, 1) & 0x70) {    /* check error stat */
    ZWRITE0(port, 0x30);          /* reset error */
  }
}


/*
 *  _162Bug_output_char
 *
 *  Output a single character using the 162Bug functions.  The character
 *  will be written to the default output port.
 */

void _162Bug_output_char( char c )
{
  asm volatile( "moveb  %0, -(%%sp)\n\t"   /* char to output */
                "trap   #15\n\t"           /* Trap to 162Bug */
                ".short 0x20"              /* Code for .OUTCHR */
    :: "d" (c) );
}


/*
 *  _BSP_output_char
 *
 *  printk() function prototyped in bspIo.h. Does not use termios.
 *
 *  If we have initialized the console device then use it, otherwise
 *  use the 162Bug routines to send it to the default output port.
 */

void _BSP_output_char(char c)
{
  if (Console_Is_Initialized)
    putchar(c);
  else
    _162Bug_output_char(c);

  if ('\n' == c)
    _BSP_output_char('\r');
}


rtems_device_driver console_initialize(
  rtems_device_major_number  major,
  rtems_device_minor_number  minor,
  void                      *arg
)
{
  int     i;
  rtems_status_code status;

  /*
   * Initialise receiver interrupts on both ports
   */

  for (i = 0; i <= 1; i++) {
    Ring_buffer_Initialize( &Console_Buffer[i] );
    ZWRITE(i, 2, SCC_VECTOR);
    ZWRITE(i, 10, 0);
    ZWRITE(i, 1, 0x10);     /* int on all Rx chars or special condition */
    ZWRITE(i, 9, 8);        /* master interrupt enable */
  }

  set_vector(C_Receive_ISR, SCC_VECTOR, 1); /* install ISR for ports A and
B */

  mcchip->vector_base = 0;
  mcchip->gen_control = 2;        /* MIEN */
  mcchip->SCC_int_ctl = 0x13;     /* SCC IEN, IPL3 */

  status = rtems_io_register_name(
    "/dev/console",
    major,
    (rtems_device_minor_number) 1
  );

  if (status != RTEMS_SUCCESSFUL)
    rtems_fatal_error_occurred(status);

  status = rtems_io_register_name(
    "/dev/tty00",
    major,
    (rtems_device_minor_number) 0
  );

  if (status != RTEMS_SUCCESSFUL)
    rtems_fatal_error_occurred(status);

  status = rtems_io_register_name(
    "/dev/tty01",
    major,
    (rtems_device_minor_number) 1
  );

  if (status != RTEMS_SUCCESSFUL)
    rtems_fatal_error_occurred(status);

  return RTEMS_SUCCESSFUL;
}

/*
 *   Non-blocking char input
 */

bool char_ready(int port, char *ch)
{
  if ( Ring_buffer_Is_empty( &Console_Buffer[port] ) )
    return false;

  Ring_buffer_Remove_character( &Console_Buffer[port], *ch );

  return true;
}

/*
 *   Block on char input
 */

char inbyte(int port)
{
  char tmp_char;

  while ( !char_ready(port, &tmp_char) );
  return tmp_char;
}

/*
 *   This routine transmits a character out the SCC.  It no longer supports
 *   XON/XOFF flow control.
 */

void outbyte(char ch, int port)
{
  while (1) {
    if (ZREAD0(port) & TX_BUFFER_EMPTY) break;
  }
  ZWRITED(port, ch);
}

/*
 *  Open entry point
 */

rtems_device_driver console_open(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return RTEMS_SUCCESSFUL;
}

/*
 *  Close entry point
 */

rtems_device_driver console_close(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return RTEMS_SUCCESSFUL;
}

/*
 * read bytes from the serial port. We only have stdin.
 */

rtems_device_driver console_read(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  rtems_libio_rw_args_t *rw_args;
  char *buffer;
  int maximum;
  int count = 0;

  rw_args = (rtems_libio_rw_args_t *) arg;

  buffer = rw_args->buffer;
  maximum = rw_args->count;

  if ( minor > 1 )
    return RTEMS_INVALID_NUMBER;

  for (count = 0; count < maximum; count++) {
    buffer[ count ] = inbyte( minor );
    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
      buffer[ count++ ]  = '\n';
      break;
    }
  }

  rw_args->bytes_moved = count;
  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
}

/*
 * write bytes to the serial port. Stdout and stderr are the same.
 */

rtems_device_driver console_write(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  int count;
  int maximum;
  rtems_libio_rw_args_t *rw_args;
  char *buffer;

  rw_args = (rtems_libio_rw_args_t *) arg;

  buffer = rw_args->buffer;
  maximum = rw_args->count;

  if ( minor > 1 )
    return RTEMS_INVALID_NUMBER;

  for (count = 0; count < maximum; count++) {
    if ( buffer[ count ] == '\n') {
      outbyte('\r', minor );
    }
    outbyte( buffer[ count ], minor  );
  }

  rw_args->bytes_moved = maximum;
  return 0;
}

/*
 *  IO Control entry point
 */

rtems_device_driver console_control(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return RTEMS_SUCCESSFUL;
}




/*---------------------------------------------------------------------*/



Hoping earliest replies.






AJAI KUMAR MEDHAVI
SCIENTIFIC OFFICER
RAJA RAMMANNA CENTRE FOR ADVANCED TECHNOLGY
DEPARTMENT OF ATOMIC ENERGY, GOV. OF INDIA,
PO : CAT, INDORE-452013, INDIA
PH. 91-731-2488052


-- 




More information about the users mailing list