EmbeddedRelated.com
Forums

How to manipulate a receiving buffer

Started by Steven Woody April 3, 2007
On 4 Apr 2007 08:47:46 -0700, "Dave Pollum" <vze24h5m@verizon.net>
wrote:

SNIP!
> >I've used double buffering with packet/protocol logic in the ISR, and >that works well. However, if you don't want the packet logic in the >ISR, you could still use double buffering. The ISR could mark a >buffer as ready for the upper level code, and then store more >characters in the _other_ buffer. Ready could be set if the buffer is >full, or if a certain amount of time has passed and no new characters >have been received. The ISR can save the numbers of bytes received in >a variable associated with that buffer (use a struct - see below). >After the upper level code has read all of the chars from the buffer, >it as available. The ISR can then use that buffer again. Disabling >and restoring interrupts aren't needed. This eliminates the need for >both the ISR code and the upper level code to write to the count >(buff_len) variable. > > typedef struct { > char nbr_bytes_read; /* 0..255 */ > char OK_to_read_buffer; /* T/F */ > char buffer[ BUFF_SZ ]; > } buffer_stuff; > buffer_stuff *buffer_1; > buffer_stuff *buffer_2; > >-Dave Pollum >
How do you handle swtiching between the two buffers cleanly and quickly? I've written some code but it's a bit of a dogs dinner (too many if statements)! Also what do you do when both buffers are full and are marked as OK_to_read_buffer? Just empty the data into a bin bucket until one gets freed? Thanks.
On Apr 11, 2:05 pm, Michael Frederick <n...@email.address> wrote:
> On 4 Apr 2007 08:47:46 -0700, "Dave Pollum" <vze24...@verizon.net> > wrote: > > SNIP! > > > > >I've used double buffering with packet/protocol logic in the ISR, and > >that works well. However, if you don't want the packet logic in the > >ISR, you could still use double buffering. The ISR could mark a > >buffer as ready for the upper level code, and then store more > >characters in the _other_ buffer. Ready could be set if the buffer is > >full, or if a certain amount of time has passed and no new characters > >have been received. The ISR can save the numbers of bytes received in > >a variable associated with that buffer (use a struct - see below). > >After the upper level code has read all of the chars from the buffer, > >it as available. The ISR can then use that buffer again. Disabling > >and restoring interrupts aren't needed. This eliminates the need for > >both the ISR code and the upper level code to write to the count > >(buff_len) variable. > > > typedef struct { > > char nbr_bytes_read; /* 0..255 */ > > char OK_to_read_buffer; /* T/F */ > > char buffer[ BUFF_SZ ]; > > } buffer_stuff; > > buffer_stuff *buffer_1; > > buffer_stuff *buffer_2; > > >-Dave Pollum > > How do you handle swtiching between the two buffers cleanly and > quickly? I've written some code but it's a bit of a dogs dinner (too > many if statements)!
You use pointers to refer to the buffers. The code is the same regardless of which buffer the pointer points to.
> Also what do you do when both buffers are full and are marked as > OK_to_read_buffer? Just empty the data into a bin bucket until one > gets freed?
If you receive data faster than you can process it, you either have to have large enough buffers to hold all of the data or you have to drop messages. In general, double (or triple) buffers are used when you can process the data as fast as it arrives on the average and you won't need to continue to buffer it. Triple buffers are used if the data is coming in at a fixed rate and the data goes out at a fixed rate, but there is some latency inbetween. The first buffer is filled and processing starts, but the processing takes nearly as long as the message rate. So as the first buffer is emptied out the second becomes full and the processor has not yet released the first buffer. A third buffer makes it all work without a hitch. I expect this is needed more often when the whole thing is being done in hardware. If your processing in software is that close to not keeping up, it is likely to not work reliably.
Steven Woody wrote:
> i am writting problem to receive data from a interrupt-driven serial > port, and i think my code will always have change of lossing data. > > in the receving ISR, i get a byte from a register and put it into a > buffer, > > static unsigned char buff[ BUFF_SIZE ]; > static buff_len = 0; > > __interrupt on_byte_in( void ) > { > if ( buffer_len < sizeof( buff ) ) > buffer[ buffer_len++ ] = the_byte_in_the_register; > } > > another function used to fetch the buffer data, > > flush_receiving_buff( void ) > { > for ( size_t i = 0; i < buff_len; ++i ) { > process the buff[ i ]; > buff_len = 0; ------------- (a) > } > > my question is that, during the execution of statement (a), one or > more new bytes might come in and code above will lost them. if you > folks see the problem, can you please suggest me a solution? i believe > the question is very basic and must have been well resolved. > > thanks in advance.
Consider adding a write index and a read index. The ISR increments the write index while the reading routine increments the read index. -- EventStudio 4.0 - http://www.EventHelix.com/EventStudio Model in Plain Text; Generate Sequence Diagrams in PDF/Word