Page 1 of 1

Serial Input on MOD5270

Posted: Thu Dec 23, 2010 7:59 am
by BMillikan
I am trying to implement a serial interface on a MOD5270 development board. But it seems that I can only read 1 character from the port at a time. Why is this? I am doing a select() on the port followed by a read(). Here is the code snippet...

while (1)
{
FD_ZERO( &read_fds );
FD_SET( fdserial, &read_fds );

FD_ZERO( &error_fds );
FD_SET( fdserial, &error_fds );

if ( select( FD_SETSIZE,
&read_fds,
( fd_set * ) 0,
( fd_set * ) 0,
20 ) )
{

if ( FD_ISSET( fdserial, &read_fds ) )
{

OSLock();

n = read(fdserial, &buffer[0], BUFFER_SIZE);

OSUnlock();
}
}

putleds(toggle);
toggle ^= 1;
}

Re: Serial Input on MOD5270

Posted: Thu Dec 23, 2010 9:23 am
by Chris Ruff
Why lock the OS? I never do this. Have you seen this done somewhere? The OS needs to continue working for the file descriptors to be processed by other (netburner core) threads

Chris

Re: Serial Input on MOD5270

Posted: Thu Dec 23, 2010 9:36 am
by v8dave
I don't see any OSTimeDly in your code to yield to other tasks (assuming more than 1) either so it is possible that you are just running much faster through your loop than the data is available. What is your baud rate for the serial port? I am not familiar with SELECT as I have not used this.

Chris is also right, you don't need the locks on the OS during reading as long as only one task at a time is reading the port which is what you want anyway.

Try putting in a delay as a test, something like OSTimeDly(TICKS_PER_SECOND) which will wait 1 second before it continues and see if you read more data this time. Put this before the read() call.

It all depends on what your data is, but you may have to delay whilst data arrives. I use a timeout based on a number of character lengths for some projects (MODBUS etc) and others are based on recieving certain characters to delimit the reception (carriage return is common)

Dave...

Re: Serial Input on MOD5270

Posted: Thu Dec 23, 2010 10:02 am
by Chris Ruff
select() is a blocking call. It is not necessary to provide an OSTimeDly() in a task that is blocking on select();

The only time you need OSTimeDly() is in a task that is of your own construction that does not block. If you had a task:

taskBuh(iforget)
{
while(1)
{
for(int i=0;i<10;i++)
{
printf("I own the world!!!!\n");
}
}
}


This task will stop everything in its tracks. IT would need an


OSTimeDly()

before the closing brace
to allow anything else to run
Chris

Re: Serial Input on MOD5270

Posted: Tue Dec 28, 2010 6:57 am
by Ridgeglider
I agree with Chris: avoid the OSLock. Next, during your inits, I'd recommend closing and then re-opening the serial ports using SerialClose() and then OpenSerial(). This will ensure the serial ports are using the interrupt-based drivers instread of the default polled serial drivers. See the Serial Library chapter in C:\nburn\docs\NetBurnerRuntimeLibrary\NetBurnerRuntimeLibraries.pdf. Next, be careful with the read() call. If data is available (via the serial ISR), read() will read "at least" one char. That means your code must handle varying amounts of char input and therefore depending on what you are doing, you may not want the results of the read to always go to buffer[0] and, if so, you probaby want to be sure the buffer is not over-run by controlling the number of chars to read. See the I/O System Library chapter in the same PDF for a description of read(). I think, in your case, the combination of using the polled drivers and locking the OS pretty much ensures getting only one char at a time. If you enable the interrupt-based drivers, read() will grab all the chars the ISR has rec'd. Note that in some situations this means, if no chars are available, the system may hang until one char is available. You might want to check out ReadWithTimeout to avoid an apparent "hung" system if no char has been rec'd. Then again, in your case select() will not trip unless there is a read event (ie at least one char). Note that it is also possible to use select() with a timeout. Sometimes, detecting a pause via such a short. (1-3 tick) timeout is a good way to detect receipt of a full sentence in cases where periodic blurts of data, (say from a gps) are typical. If so, if select() times out, you probably have a full sentence ready to parse.

Re: Serial Input on MOD5270

Posted: Mon Jan 03, 2011 2:00 pm
by pbreed
Select wakes you up on every received char, you will not see more than one char unless
you've been busy elsewhere for long enough for more than one char to arrive.
At 115200 baud each max char rate is ~11Khz, I have customers that
routinely have 200Khz repetitive interrupts. If all your doing is task switching (no real work)
the you could easily average 500K task switches a second.

The byte count passed to read are the MAX it will read not the minimum.
read will return with whatever is left in the buffer, usually just one char.


In general don't use OSLock unless you have a shared data structure
you are trying to protect. in that case its probably better to use
a OS_CRIT that way you only stop task switching when some other task needs the
data struct. If your accessing the data struct from a user written interrupt, then USER_ENTER_CRITICAL/USER_EXIT_CRITICAL is
a better choice as OSLock does not block interrupts.