CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Purging UART data in the receive buffer
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 24, 2022 6:30 am     Reply with quote

You should also consider a 'timed UART receive'. CCS shows a sample in the Q&A section of the manual.
You need to calculate how long a 'good' receive will take ( say 10ms). You then preload a timer for 20ms ( double the expected time to get the data..).
The 'timed serial ISR' will either finish(return) when either all data is received OR the 'timeout' occours. Using this technique means the program will not 'hang' in the serial ISR.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Mon Apr 25, 2022 7:59 pm     Reply with quote

Thank you, Temtronic, for your suggestion. Are you referring to page 334 of the November 2021 manual?
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Mon Jun 20, 2022 11:56 pm     Reply with quote

I gathered from the forum posts that it is generally best to stay in an ISR for as short a time as possible, so that the MCU can attend to other tasks if needed.

However, if I expect to receive a stream of bytes of data (say 200 of them) from a UART, and wish to ensure minimal chance of the data getting missed or corrupted because the MCU attends to other interrupts while receiving the data, would it make sense to complete reading all the bytes within the ISR (for #int_rda, for example) when the first UART interrupt occurs, instead of reading one byte per interrupt?

I will appreciate any comments or suggestions. Thank you.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Jun 21, 2022 12:20 am     Reply with quote

Generally, UART data is so slow that it is not worth worrying about this.
Understand that a UART character takes 10 bit times (or more), so even
at 115200bps, this is 87uSec, on a chip at (say) 16MHz, this is 350
instructions, so i is very rare for a second character to have arrived by
the time you are leaving the interrupt.
The exception is with chips that have much larger receive buffers (so the
DsPIC's for example), and/or when using very high baud rates:
Code:

#INT_RDA
void character_rx(void)
{
   int t;
   do
   {
      buffer[next_in]=getc();
      t=next_in;
      if (++next_in >=BUFFER_SIZE)
          next_in=0;    //wrap the buffer size
      if(next_in==next_out)
         next_in=t;      // Buffer full !!   
   } (while kbhit());  // loop if another character has arrived.
}


This shows how to efficiently have the receive 'loop' if another character
has arrived before the exit. Also how to correctly handle the buffer size
wrapping (this copes with buffer sizes that are not 'binary' sizes, the
supplied example file has problems if these are used).
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Tue Jun 21, 2022 9:15 pm     Reply with quote

Thank you, Ttelmah, for helping me see the UART data transmission time in perspective.

1. If, due to some delay in servicing a UART interrupt, there is more than one byte of data in the receive buffer at the time the corresponding UART ISR is called, but the ISR reads only one byte and then exits, will another UART interrupt (caused by the presence of data in the receive buffer) be triggered immediately after the ISR exits?
2. If no, would it be appropriate in general to do a similar do-while loop to read all characters in the receive buffer whenever a UART ISR is called, in case there is more than one character in the receive buffer?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Tue Jun 21, 2022 11:19 pm     Reply with quote

Understand that the standard PIC only has one actual buffer character.
Has the incoming shift register, and one buffer. So 1.9999 characters max.
Now the only occassion where kbhit will test true is when the final bit
at the end of the character arrives between the moment the character
is read, and the test. Almost impossible.
With normal handling the ISR should have been left hundreds of instructions
before the next character arrives.
Yes, if there is another character to read, the ISR will just be called again.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Wed Jun 22, 2022 12:41 am     Reply with quote

Thank you, Ttelmah. Hope you do not mind that I continue to pursue this enquiry.

For the PIC18LF46K22, the datasheet says “The FIFO buffering allows reception of two complete characters and the start of a third character before software must start servicing the EUSART receiver” (Section 16.1.2). In other places, it says “two-character input buffer” (Section 16.0) and “The receive FIFO buffer can hold two characters. An overrun error will be generated if a third character, in its entirety, is received before the FIFO is accessed” (Section 16.1.2.6).

So, is it correct that for the PIC18LF46K22, it is possible to have two complete characters in the receive buffer waiting to be read?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Jun 22, 2022 3:43 am     Reply with quote

This is one of the differences between the USART (most chips), and the
EUSART. However the timing remains the same. Even working at 115200bps
if all your ISR's are kept short (so the INT_RDA cannot be left 'unserviced'
because the processor is stuck in another interrupt), you should never see
another character arrive while still handling the first.
I've used RS485 serial links at 1Mbps, and have never seen a second
character arrive and be available before leaving the ISR.
The exception would be if you had an ISR for something else, that took
more than a character time to be serviced. In this situation, unless using
hardware priorities, you have the potential for a second character to
arrive before the ISR is serviced, if the processor is busy servicing the other
interrupt, when the first character arrives.
Key point is that the RDA interrupt flag cannot actually be cleared until the
FIFO is empty. Hence the interrupt will just be called immediately again
if a second character is available.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Sun Nov 27, 2022 12:27 am     Reply with quote

This is about the timeout option in the "#use RS232" directive.

The manual says this:
"TIMEOUT=x - To set the time getc() waits for a byte in milliseconds. If no character comes in within this time the RS232_ERRORS is set to 0 as well as the return value from getc(). This works for both UART and non-UART ports."

Questions:
(a) If I specify this timeout option, how can I access the "RS232_ERRORS" value? It seems that a value of zero for this error and a getc() return value of zero will collectively confirm that a timeout has occurred.
(b) Also, should I still include the "ERRORS" option in the "use RS232" directive?

Ultimately, I would like to know how the program can definitively detect a timeout when it has occurred, if this option is used?

I am looking into using this option, instead of writing code, to detect a character-receive timeout.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Nov 27, 2022 4:54 am     Reply with quote

RS232_ERRORS is a system created variable.
It will show in the symbol table for your project.
It is created when you use any #USR RS232 option that requires it
(ERRORS, 9bits, or TIMEOUT).
You can just read it as with any other variable. It contains normally a
copy of the RCSTA register for the UART. So is used to detect overrun and
framing errors and the 9th data bit when using 9bit mode without using
'LONG_DATA'.
Since RCSTA always has bit 7 set when the UART is enabled. For the timeout,
if bit 7 is set, a timeout has not occurred, but if it is clear then a timeout
has happened. (numbering 0..7).
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Nov 27, 2022 6:47 am     Reply with quote

re: (b)...
yes, always add 'ERRORS' ! Without it, the HW UART can 'freeze', 'lockup', 'stop' and the PIC will sit there 'dead' until YOU power down the PIC.
The compiler adds a small chunk of code to prevent this 'locking up' situation.


re: TIMEOUT
Since this is 'per character', the timeout value 'should' be say x2 the time it takes for one character to be processed. Say you're running at 9600 baud, that's about 1ms per character, so timeout 'should' be set for 2ms.

Ideally set the timeout value for as short as possible yet allows for some extra time, maybe 3 bits worth of time ? A character, to me, is normally 10 bits (start-data-stop). 2 bit times might be a good compromise, long enough to get good data, short enough to be fast ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Nov 27, 2022 7:12 am     Reply with quote

and, since it will never be 'zero' for a normal UART transaction, they chose
this to make it really easy to test. ==0 -> timeout has happened.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group