Re: Safe way to write interrupt driven circular buffer tx rx?



Dave Hansen wrote:
On Aug 29, 11:54 am, Stefan Reuther <stefan.n...@xxxxxxxx> wrote:
cs_post...@xxxxxxxxxxx wrote:
The interruptible process modifies the buffer variables in only one
small block of code, which is bracketed with interrupt disable &
enable instructions.

You can avoid that interrupt disable by using head and tail variables
instead of head and count. The interrupt would then modify only the head
(and read the tail to check for overflow), the interruptible process
would modify only the tail (and read the head to check whether anything
is in the buffer).

This is the way I do it. A couple small things to watch:

1) You must _always_ have at least one empty slot in your buffer. You
can probably figure out why for yourself (hint: what does head==tail
mean?).

If the number of slots is a power of two, and your head/tail variables
have more bits than needed to represent the number of slots, you can
also use the final slot. Quick&dirty:
#define N 128
volatile unsigned int head, tail;
volatile char buffer[N];
unsigned int inuse() { return head - tail; }
void put(char c) { if (inuse() != N) { buffer[head++%N] = c; } }
void get(char* c) { if (inuse() != 0) { *c = buffer[tail++%N]; } }

2) You can avoid critical sections (e.g., disabling interrupts) only
if access to the head and tail variables is atomic. For example, if
head and tail are 16 bits wide, and you're running on an AVR or 8051,
you'll still have to protect access to the variables in your main-line
code.

3) Even if access to the head an tail variables is atomic, you must
still be careful about how you order your code. Always check the full/
empty status first. Then copy the data. Update the index last.

And don't forget the 'volatile' qualifiers and, if you're doing a
multi-core application, the memory barriers.


Stefan

.



Relevant Pages

  • Re: Python Doc Problem Example: os.path.split
    ... I was working on a program where i needed to split a path into dirname, ... > Split the pathname path into a pair, (head, tail) where tail is the ... > last pathname component and head is everything leading up to that. ... > tail part will never contain a slash; if path ends in a slash, ...
    (comp.unix.programmer)
  • Re: Using a link list over an array.
    ... compile (p->data is a void *) so you have not shown us some key ... int cmp ... head = list_sort; ... list_type *tail; ...
    (comp.lang.c)
  • HELP for doubly linked list
    ... forward and one pointing backwards. ... You must be able to insert a new node at the head of the ... You must be able to insert a new node at the tail of the ... tail, F – display contents forward, B – display contents backwards, ...
    (microsoft.public.dotnet.languages.vc)
  • Re: Linked List
    ... pete wrote: ... int main ... head = tail = NULL; ... head = list_sort; ...
    (comp.lang.c)
  • HELP for doubly linked list
    ... forward and one pointing backwards. ... You must be able to insert a new node at the head of the ... You must be able to insert a new node at the tail of the ... tail, F – display contents forward, B – display contents backwards, ...
    (microsoft.public.dotnet.languages.vc)