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