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 CCS Technical Support

receive_buffer in CCS V5

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Orcino



Joined: 07 Sep 2003
Posts: 56

View user's profile Send private message

receive_buffer in CCS V5
PostPosted: Tue Sep 10, 2013 6:56 am     Reply with quote

Hi, Can anyone give any examples of how to use the RECEIVE_BUFFER, this in version 5 ?

Currently I use the following code and I want to test this new feature of the compiler.

Code:

#int_rda
void  RDA_isr(void)
 {                             
    do {
       receiveString[next_in]=getc();
     
        if (++next_in >=BUFFERSIZE)
                  next_in=0;
     
        if(next_in==next_out)
                {
                if (++next_out >= BUFFERSIZE)
                          next_out=0;
                }
         
       } while(kbhit());
 }
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Sep 10, 2013 8:07 am     Reply with quote

Stick with the existing....

There is actually nothing whatsoever to do, to use this feature. Just change the #use rs232, adding the following:

RECEIVE_BUFFER=BUFFERSIZE

and get rid of your INT_RDA

However it has problems.

There is no testing at all for the buffer being full. Results in data being completely 'garbaged' if the buffer overflows. Same applies if you use TX buffering.

If this could happen, you end up having to add your own code to intercept their RCV_NEXT_IN_1, and RCV_NEXT_OUT_1 values, and test for overflows. it's more work than just doing it yourself.

I hoped they would do something like set a status bit in RS232_ERRORS when the buffer is full.

You just use kbhit, getc, and puts in your code, and they talk to the buffer instead of to the port.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Sep 10, 2013 8:08 am     Reply with quote

Interesting... I don't have V5 yet. However, I would never manipulate the out/read pointer to my buffer in the in/write ISR. Sure, you want to make sure you don't try to write into a full buffer, but other than that, there's no reason for the ISR to do anything to the out/read pointer/counter.

Due to the fact that any variable other than a byte is not inherently atomic on most PICs (i.e. 16s & 18s), I usually keep buffer lengths to 256 characters or less. I also use a count rather than compare pointers/array indexes, and always go fully circular rather than worrying about message size. I also avoid buffers in structures - as tempting as a object orientated structure approach might be, it involves significant overhead. Even so, read/modify/write buffer operations may need to be critical section locked to avoid buffer corruption. I'd have done something like this totally untested code:

Code:


// Buffer size should ideally be a power of two and no more than 256 for this code.
#define IN_BUFFERSIZE 128
byte In_Buffer[IN_BUFFERSIZE];
unsigned int8 next_in = 0;
unsigned int8 next_out = 0;
unsigned int8 In_Buf_Count = 0;

// Input buffer write. Note, this increments In_Buf_Count, the read routine
// decrements it.
#int_rda
void  RDA_isr(void)
 {                         
       byte ch;

       // Always read the character.
       ch = getc();
       
       // Can we fit this character into the buffer?
        if (In_Buf_Count < IN_BUFFERSIZE)
        {
            // Yes, so store it.
            receiveString[next_in++] = ch;
               
            // Wrap the buffer write index.
            if (next_in >= IN_BUFFERSIZE)
            {
                  next_in=0;
            }
       }
 }

byte In_Buffer_Read(void)
{
    byte ch = 0;
    // We will return null if buffer is empty.
    if (In_Buf_Count)
    {
         // There is at least one character in the buffer. Get the next available character.
         ch = receiveString[next_out++];
               
         // Wrap the buffer read index.
        if (next_out >= IN_BUFFERSIZE)
        {
            next_out=0;
        }

        // Decrement the buffer count. It doesn't matter if an interrupt
        // has happened since we read it.
        In_Buf_Count--;
    }
    return ch;
}
   


Also, and RDA interrupt means there is a byte available to be read from the UART. Unless there is a FIFO AND there are ISRs or critical sections longer than the time taken to send a character, then you know there will be one and only one character for every RDA interrupt, hence a while (kbhit()) loop is pointless and simply increases ISR execution time.

As I haven't yet got V5 I can't say how it does this sort of thing.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Tue Sep 10, 2013 9:49 am     Reply with quote

His buffer routine is fine.

He only 'wraps' the pointer when he reaches the end of the buffer (the posted method is the best 'generic' way of doing this whatever the buffer size), and avoids overfilling.

The code is more efficient than using separate addresses and count as you show....

His routine throws away the oldest character, when the buffer fills, which is sometimes preferred.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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