Avantha Jayawickreme
08/17/2010 11:21 PM
post63360
|
Hey all!
I am having difficulty reading from the serial port, it is being controlled by interrupts when the data comes in, it is
supposed to be roughly 1Hz (depends on GPS signal and stuff)
I am encountering 2 problems:
1: Is that when i read using Interrupts so the serial port interrupts when the data is ready to be read, that happens
roughly 1Hz, then after that i for some reason get like roughly 20(give or take) interrupts one after another which
also reads the data (its not supposed to do this, because the program on the IMU that i am using outputs data roughly
every 1Hz).
2: After i perform the read I noticed that the data in the serial port doesn;t get updated for some reason, and the data
that is in the serial port is only maxed at 2048 bytes(anyone know why this is?), it only gets updated when i perform
an InterruptWait() and corresponding InterruptUnmask() when this happens I found out that the data in the serial port
gets refreshed 8 bytes at a time, so eventually after say 2048 - 167 *(amount of reads), the data in the serial port
runs out and ruins my whole output.
To counteract that problem i put in a while loop (which is in the code below).
To make sure I only read when there is more then 167 bytes.
CODE: FOR READING FROM SERIAL PORT
while(1){
InterruptWait( 0, NULL );
//THE LOOP BELOW IS WHAT I USE TO MAKE SURE THERE IS MORE THEN 167 BYTES BEFORE I READ
while (tcischars(fd)<(167))
{
InterruptUnmask( IRQ, intr_id );
InterruptWait(0,NULL);
}
numRead = read(fd, buffer, SIZE_BUFFER);
printf("\n numREAD %d\n",numRead);
/*WRITE*/
printf("%s",buffer);
write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
/* Reenable this interrupt since writing is finished */
InterruptUnmask( IRQ, intr_id );
}
CODE FOR SETTING UP SERIAL PORT
The IMU has to be read at 9600baud No flow contorl no parity and read 8 Bits at a time (ASCII)
int open_port(void)
{
int fd; /* File descriptor for the port */
struct termios termios_p; /*termios structure*/
fd = open("/dev/ser1", O_RDONLY | O_NOCTTY );
if (fd == -1)
{
perror("open_port: Unable to open /dev/ser1 - ");
return 0;
}
else
printf ("port opened\n");
tcgetattr(fd, &termios_p); /*read in the current settings*/
cfsetispeed(&termios_p, BAUD_RATE); //set input baud
cfsetospeed(&termios_p, BAUD_RATE); //set output baud
termios_p.c_cflag &= ~PARENB; //no parity bit (error checking bit)
termios_p.c_cflag &= ~CSIZE;
termios_p.c_cflag |= CS8; //set number of bits to 8
termios_p.c_cflag &=~ IHFLOW ; //disable input h/w flow control
termios_p.c_cflag &= ~OHFLOW ; //disable output h/w flow control
tcsetattr(fd, TCSANOW, &termios_p);
return (fd);
}
Can anyone please help me?
I am going crazy :(
Thanks.
|
|
|
Mario Charest
|
RE: Reading from serial port
|
Mario Charest
08/18/2010 8:14 AM
post63372
|
RE: Reading from serial port
You CANNOT mix using hardware interrupts and going through a the serial port driver. It`s either one or the other. You
are disabling interrupt while writing to disk and to the screen, this is real bad because these operation can take a
long time, and you lucking the disc controller is not using the same interrupt as the serial port ;-)
Basically your approach is all wrong. Either you totally take control of the hardware and kill devc-8250 or you rely
totally on the driver.
You code should look something like
open_port();
ssize_t rssize;
#define SIZE_BUFFER 167
char buffer[SIZE_BUFFER];
while (1 )
{
rssize = read(fd, buffer, SIZE_BUFFER); // this will block until SIZE_BUFFER bytes has been received, no need to use
interrupt
if ( rrsize != SIZE_BUFFER )
{
// handle error or the fact that not all data has bee received
}
else
{
printf("\n numREAD %d\n",numRead);
/*WRITE*/
printf("%s",buffer);
write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
}
-----Message d'origine-----
De : Avantha Jayawickreme [mailto:community-noreply@qnx.com]
Envoyé : 17 août 2010 23:22
À : momenticsgs-community
Objet : Reading from serial port
Hey all!
I am having difficulty reading from the serial port, it is being controlled by interrupts when the data comes in, it is
supposed to be roughly 1Hz (depends on GPS signal and stuff) I am encountering 2 problems:
1: Is that when i read using Interrupts so the serial port interrupts when the data is ready to be read, that happens
roughly 1Hz, then after that i for some reason get like roughly 20(give or take) interrupts one after another which
also reads the data (its not supposed to do this, because the program on the IMU that i am using outputs data roughly
every 1Hz).
2: After i perform the read I noticed that the data in the serial port doesn;t get updated for some reason, and the data
that is in the serial port is only maxed at 2048 bytes(anyone know why this is?), it only gets updated when i perform
an InterruptWait() and corresponding InterruptUnmask() when this happens I found out that the data in the serial port
gets refreshed 8 bytes at a time, so eventually after say 2048 - 167 *(amount of reads), the data in the serial port
runs out and ruins my whole output.
To counteract that problem i put in a while loop (which is in the code below).
To make sure I only read when there is more then 167 bytes.
CODE: FOR READING FROM SERIAL PORT
while(1){
InterruptWait( 0, NULL );
//THE LOOP BELOW IS WHAT I USE TO MAKE SURE THERE IS MORE THEN 167 BYTES BEFORE I READ
while (tcischars(fd)<(167))
{
InterruptUnmask( IRQ, intr_id );
InterruptWait(0,NULL);
}
numRead = read(fd, buffer, SIZE_BUFFER);
printf("\n numREAD %d\n",numRead);
/*WRITE*/
printf("%s",buffer);
write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
/* Reenable this interrupt since writing is finished */
InterruptUnmask( IRQ, intr_id );
}
CODE FOR SETTING UP SERIAL PORT
The IMU has to be read at 9600baud No flow contorl no parity and read 8 Bits at a time (ASCII)
int open_port(void)
{
int fd; /* File descriptor for the port */
struct termios termios_p; /*termios structure*/
fd = open("/dev/ser1", O_RDONLY | O_NOCTTY );
if (fd == -1)
{
perror("open_port: Unable to open /dev/ser1 - ");
return 0;
}
else
printf ("port opened\n");
tcgetattr(fd, &termios_p); /*read in the current settings*/
cfsetispeed(&termios_p, BAUD_RATE); //set input baud
cfsetospeed(&termios_p, BAUD_RATE); //set output baud
termios_p.c_cflag &= ~PARENB; //no parity bit (error checking bit)
termios_p.c_cflag &= ~CSIZE;
termios_p.c_cflag |= CS8; //set number of...
View Full Message
|
|
|
Avantha Jayawickreme
|
Re: RE: Reading from serial port
|
Avantha Jayawickreme
08/18/2010 9:22 AM
post63383
|
Re: RE: Reading from serial port
> You CANNOT mix using hardware interrupts and going through a the serial port
> driver. It`s either one or the other. You are disabling interrupt while
> writing to disk and to the screen, this is real bad because these operation
> can take a long time, and you lucking the disc controller is not using the
> same interrupt as the serial port ;-)
>
> Basically your approach is all wrong. Either you totally take control of the
> hardware and kill devc-8250 or you rely totally on the driver.
>
> You code should look something like
>
> open_port();
> ssize_t rssize;
> #define SIZE_BUFFER 167
> char buffer[SIZE_BUFFER];
> while (1 )
> {
> rssize = read(fd, buffer, SIZE_BUFFER); // this will block until
> SIZE_BUFFER bytes has been received, no need to use interrupt
> if ( rrsize != SIZE_BUFFER )
> {
> // handle error or the fact that not all data has bee received
> }
> else
> {
> printf("\n numREAD %d\n",numRead);
> /*WRITE*/
> printf("%s",buffer);
> write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
> }
>
Hey Mario, thanks heaps for that! Cleared up the interrupt thingy,
But still having a problem with the read, it reads it a couple of times
then it goes into the else and prints -1 as read failed,
here is the code i implemented from your suggestion,
CODE:: I declared ssize_t rssize; locally in the function that is performing the read
ALSO BTW: I am giving the thread permission to access hardware with the following:
/* Give this thread root permissions to access the hardware */
privity_err = ThreadCtl( _NTO_TCTL_IO, NULL );
if ( privity_err == -1 ) { printf( "Can't get root permissions\n" );
return -1;
}
while(1){
rssize = read(fd, buffer, SIZE_BUFFER); // this will block until SIZE_BUFFER bytes has been received, no need to
use
if ( rssize != SIZE_BUFFER )
{
// handle error or the fact that not all data has bee received
printf("\n numREAD %d\n",rssize); //IT GOES INTO HERE AFTER A COUPLE OF READS LIKE 20 TIME OR SO
}
else
{
printf("\n numREAD %d\n",rssize);
/*WRITE*/
printf("%s",buffer);
write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
}
}
So was my termios structure right for setting up the serial port,
Also here is the .build file set up of the serial port using devc-8250
#######################################################################
## serial driver
display_msg Starting Serial Com...
devc-ser8250 0x3F8,4 0x2F8,3 -t 8 -b 9600 &
# Start a debug server for debugging programs
waitfor /dev/ser1
waitfor /dev/ser2
stty par=none -ihflow -ohflow +cs8 stopb=1
Thanks so much for you help Mario, really appreciate it!
Please let me know if you require any more information from me
|
|
|
Avantha Jayawickreme
|
Re: RE: Reading from serial port
|
Avantha Jayawickreme
08/18/2010 9:24 AM
post63384
|
Re: RE: Reading from serial port
Sorry disregard the attached file the proper file is here
|
|
|
Mario Charest
|
RE: RE: Reading from serial port
|
Mario Charest
08/18/2010 9:32 AM
post63388
|
RE: RE: Reading from serial port
If it`s -1 it`s an error condition, print errno to get more information about the error. No need to call
InterruptAttachEvent(), I might be why it`s not working.
Also note that since your buffer is 2048 bytes, read() will not return until it has read the 2048 bytes. This means
that if the message that the GPS send is 167 bytes, it will take a bunch of "packet" before read() returns. You might
want to use readcond instead of read, to handle timeout and stuff.
-----Message d'origine-----
De : Avantha Jayawickreme [mailto:community-noreply@qnx.com]
Envoyé : 18 août 2010 09:22
À : momenticsgs-community
Objet : Re: RE: Reading from serial port
> You CANNOT mix using hardware interrupts and going through a the
> serial port driver. It`s either one or the other. You are disabling
> interrupt while writing to disk and to the screen, this is real bad
> because these operation can take a long time, and you lucking the disc
> controller is not using the same interrupt as the serial port ;-)
>
> Basically your approach is all wrong. Either you totally take control
> of the hardware and kill devc-8250 or you rely totally on the driver.
>
> You code should look something like
>
> open_port();
> ssize_t rssize;
> #define SIZE_BUFFER 167
> char buffer[SIZE_BUFFER];
> while (1 )
> {
> rssize = read(fd, buffer, SIZE_BUFFER); // this will block until
> SIZE_BUFFER bytes has been received, no need to use interrupt
> if ( rrsize != SIZE_BUFFER )
> {
> // handle error or the fact that not all data has bee received
> }
> else
> {
> printf("\n numREAD %d\n",numRead);
> /*WRITE*/
> printf("%s",buffer);
> write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
> }
>
Hey Mario, thanks heaps for that! Cleared up the interrupt thingy,
But still having a problem with the read, it reads it a couple of times
then it goes into the else and prints -1 as read failed,
here is the code i implemented from your suggestion,
CODE:: I declared ssize_t rssize; locally in the function that is performing the read ALSO BTW: I am giving the thread
permission to access hardware with the following:
/* Give this thread root permissions to access the hardware */ privity_err = ThreadCtl( _NTO_TCTL_IO, NULL ); if (
privity_err == -1 ) { printf( "Can't get root permissions\n" ); return -1; }
while(1){
rssize = read(fd, buffer, SIZE_BUFFER); // this will block until SIZE_BUFFER bytes has been received, no need to
use
if ( rssize != SIZE_BUFFER )
{
// handle error or the fact that not all data has bee received
printf("\n numREAD %d\n",rssize); //IT GOES INTO HERE AFTER A COUPLE OF READS LIKE 20 TIME OR SO
}
else
{
printf("\n numREAD %d\n",rssize);
/*WRITE*/
printf("%s",buffer);
write(outfd,buffer,SIZE_BUFFER); //writing to file on PC/104
}
}
So was my termios structure right for setting up the serial port,
Also here is the .build file set up of the serial port using devc-8250
#######################################################################
## serial driver
display_msg Starting Serial Com...
devc-ser8250 0x3F8,4 0x2F8,3 -t 8 -b 9600 &
# Start a debug server for debugging programs
waitfor /dev/ser1
waitfor /dev/ser2
stty par=none -ihflow -ohflow +cs8 stopb=1
Thanks so much for you help Mario, really appreciate it!
Please let me know if you require any more information from me
_______________________________________________
QNX Momentics Getting Started
http://community.qnx.com/sf/go/post63383
|
|
|
Avantha Jayawickreme
|
Re: RE: RE: Reading from serial port
|
Avantha Jayawickreme
08/18/2010 10:07 AM
post63402
|
Re: RE: RE: Reading from serial port
Ok, cool thanks Mario, yeah i forgot to remove that InterruptAttach,
I will try it tomorrow morning, yeh the 2048 bytes i am not sure why its that, but ill give it a go tomorrow and fingers
crossed it works.
PS, thanks heaps!!! Was very helpful!!
|
|
|
Avantha Jayawickreme
|
Re: RE: RE: Reading from serial port
|
Avantha Jayawickreme
08/19/2010 12:56 PM
post63582
|
Re: RE: RE: Reading from serial port
Hey Mario got it working 100% now
Here is the code im using
while(1){
rssize = readcond(fd,buffer,SIZE_BUFFER,SIZE_BUFFER,0,0); //blocked here until SIZE_BUFFER bytes
if ( errno ==0 )
{
write(outfd,buffer,SIZE_BUFFER);
}
else
{
errvalue = errno;
// handle error or the fact that not all data has bee received
printf( "The error generated was %d\n That means: %s\n ", errvalue,strerror( errvalue ) );
}
}
This gets me what i need perfectly, only problem is the numbers are stored in a string, they are seperated by spaces
need to now get the data to perform calculations, any thoughts on the best way to do that ?
I have a character '*' to indicate the start of each new line of the data
* 0508 0528 0479 0522 0531 0524 0228 0000 0335 0796 0000.00000 0000.00000 0000.00000 00
I was using strchr(buffer,'*') to find the first instance of the that then using sscanf and stuff but is there a better
way to do that?
Thanks heaps for getting me on the right track!
|
|
|
Mario Charest
|
RE: RE: RE: Reading from serial port
|
Mario Charest
08/20/2010 11:50 AM
post63752
|
RE: RE: RE: Reading from serial port
I wouldn`t use readconf the way you do, the GPS string is probably say 128 bytes long, but readconf is waiting for
SIZE_BUFFER ( which is 2048 I believe), that means readconfig will only return after receving 16 data packets.
As for parsing the content of buffer, there are so many ways to do that ;-) Don`t see anything wrong with how you do it
. However I personnaly would use strtok to split each field and handle them separately. That gives me finer control and
better error handling then one big scanf.
-----Message d'origine-----
De : Avantha Jayawickreme [mailto:community-noreply@qnx.com]
Envoyé : 19 août 2010 12:56
À : momenticsgs-community
Objet : Re: RE: RE: Reading from serial port
Hey Mario got it working 100% now
Here is the code im using
while(1){
rssize = readcond(fd,buffer,SIZE_BUFFER,SIZE_BUFFER,0,0); //blocked here until SIZE_BUFFER bytes
if ( errno ==0 )
{
write(outfd,buffer,SIZE_BUFFER);
}
else
{
errvalue = errno;
// handle error or the fact that not all data has bee received
printf( "The error generated was %d\n That means: %s\n ", errvalue,strerror( errvalue ) );
}
}
This gets me what i need perfectly, only problem is the numbers are stored in a string, they are seperated by spaces
need to now get the data to perform calculations, any thoughts on the best way to do that ?
I have a character '*' to indicate the start of each new line of the data
* 0508 0528 0479 0522 0531 0524 0228 0000 0335 0796 0000.00000 0000.00000 0000.00000 00
I was using strchr(buffer,'*') to find the first instance of the that then using sscanf and stuff but is there a better
way to do that?
Thanks heaps for getting me on the right track!
_______________________________________________
QNX Momentics Getting Started
http://community.qnx.com/sf/go/post63582
|
|
|
|