We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi. I'm working on a project involving a java program and the micro controller NXP P89v664.
The java program which utilises the RXTX package, outputs to the serial port a string of characters to be deciphered by the micro controller.
My java program is completed and outputs correctly as checked by virtual com ports and a c program.
I have written a keil c program to receive the input but I somehow receive random inputs instead.
I used the _getkey() fuction to receive the input and putchar() function to check the output.
I'm new to keil c can anyone shed some light on this pls?
Thanks.
// Check if we have room for more. // We have room if r_in and r_out are less than one buffer size from each other. // So we have room if r_in - r_out doesn't overflow the masking operation performed. if (((r_in - r_out) & ~(RBUF_SIZE-1)) == 0) { // This assign will never overwrite an already used position, // because of the previous test. // And it will never overflow the buffer, because of the bit-and // giving an index modulo the buffer size. rbuf [r_in & (RBUF_SIZE-1)] = SBUF; //XXXXXXX r_in++; } else { // Our input buffer was full. Might be nice to keep track of the // number of receive buffer overflows. rbuf_overflows++; }
Your code always inserts a character, possibly killing the oldest unread character in the ring-buffer. Not only that. Since you do clipping directly after increment of r_in, you get the potential problem that r_in gets set to zero while r_out might also have been zero. So suddenly you got from a totally full ring-buffer to a ring-buffer where r_in equals r_out, signalling an empty ring-buffer. When clipping is done whenever r_in or r_out are incremented, then you must always stop inserting data exactly one step before r_in reaches r_out, to avoid making empty and full look identical.
The other code instead skips the insert if there are exactly RBUF_SIZE entries already stored in the ring buffer. And since there is no clipping of r_in or r_out when they are incremented (with the exception of the overflow from the integer storing these indices), it's ok to fill every single position in the ring buffer. You would then have exactly RBUF_SIZE entries in the buffer which can be tested by either subtracting and check if answer is >= RBUF_SIZE. Or you can perform the bit-and and check if any of the the high bits in the result got set.
So there is a difference in behaviour on overflow. One code drops the most recent characters, potentially having an else clause to warn about the overflow. The other code gets into a singularity, dropping a full buffers worth of content and starting from zero.
Most circular buffer software is written incorrectly. There are several things you need to know with circ buffers.
To accomplish all of these, you obviously need a buffer, a next-in pointer (or index), and a next-out pointer (or index). Generally, you can figure out the amount of data in the buffer by subtracting the next-out from next-in (with a modulo). However, if the result is 0, does that mean that the buffer is full or empty? This is where most circ buffer implementations fall apart.
Choosing a buffer size that is a power of 2, and using indexes for next-in and next-out, and NOT mod'ing the indexes after an increment, it is easy to answer the questions of the list above.
This is how the serial I/O routines work that I wrote when I was at Keil. This is found at http://www.keil.com/download/docs/200.asp.
The examples listed in this thread look mysteriously like the code I wrote way back when.
Jon