Can someone point out source code for a safe circular buffer receiver
transmitter? It's for sending and receiving bytes via RS232.
Reply by ●August 29, 20072007-08-29
On Aug 29, 8:21 am, "Sven" <S...@tim.com> wrote:
> Can someone point out source code for a safe circular buffer receiver
> transmitter? It's for sending and receiving bytes via RS232.
What I do is let the interrupt process freely modify the buffer count
& head variables.
The interruptible process modifies the buffer variables in only one
small block of code, which is bracketed with interrupt disable &
enable instructions.
Even if your UART only offers a simple result register for the
receive, you should be able to execute the non-interruptible section,
and then the interrupt, fast enough to not miss data at 115200 baud.
Reply by msg●August 29, 20072007-08-29
Sven wrote:
> Can someone point out source code for a safe circular buffer receiver
> transmitter? It's for sending and receiving bytes via RS232.
>
My circular buffer implementation for i8096 ( C source ) can be viewed
at http://www.cybertheque.org/homebrew/hmi-200
The ICE is currently not powered up, but on request I will do so. You
can still inspect source code and compile it however. Look for
programs with 'buffered' and 'serial' in their titles on the
'compile' page and in the 'ucos-compile' page.
Regards,
Michael
Reply by David T. Ashley●August 29, 20072007-08-29
<cs_posting@hotmail.com> wrote in message
news:1188395695.412412.51620@w3g2000hsg.googlegroups.com...
> On Aug 29, 8:21 am, "Sven" <S...@tim.com> wrote:
>> Can someone point out source code for a safe circular buffer receiver
>> transmitter? It's for sending and receiving bytes via RS232.
>
> What I do is let the interrupt process freely modify the buffer count
> & head variables.
>
> The interruptible process modifies the buffer variables in only one
> small block of code, which is bracketed with interrupt disable &
> enable instructions.
Just be aware that the critical section protocol depends on the "design
rules" for the entire embedded project.
The most common set of design rules is that for critical sections,
interrupts are disabled and enabled. The assumption is that the critical
sections will be short enough that they won't introduce any real-time
difficulties with the invocation of ISRs.
However, in some rare cases, someone may decide that a critical section
should block only interrupts of a certain type, but allow others. The
"design rules" might call for manipulating the only the SCI hardware to
implement the critical section, and only to prevent SCI interrupts.
The DI()/EI() protocol is not universally applicable, but it is nearly so.
Dave.
--
David T. Ashley (dta@e3ft.com)
http://www.e3ft.com (Consulting Home Page)
http://www.dtashley.com (Personal Home Page)
http://gpl.e3ft.com (GPL Publications and Projects)
Reply by Stefan Reuther●August 29, 20072007-08-29
cs_posting@hotmail.com wrote:
> On Aug 29, 8:21 am, "Sven" <S...@tim.com> wrote:
>>Can someone point out source code for a safe circular buffer receiver
>>transmitter? It's for sending and receiving bytes via RS232.
>
> What I do is let the interrupt process freely modify the buffer count
> & head variables.
>
> 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).
Stefan
Reply by Dave Hansen●August 29, 20072007-08-29
On Aug 29, 11:54 am, Stefan Reuther <stefan.n...@arcor.de> wrote:
> cs_post...@hotmail.com wrote:
> > On Aug 29, 8:21 am, "Sven" <S...@tim.com> wrote:
> >>Can someone point out source code for a safe circular buffer receiver
> >>transmitter? It's for sending and receiving bytes via RS232.
>
> > What I do is let the interrupt process freely modify the buffer count
> > & head variables.
>
> > 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?).
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.
Regards,
-=Dave
Reply by joe4702●August 29, 20072007-08-29
On Aug 29, 6:21 am, "Sven" <S...@tim.com> wrote:
> Can someone point out source code for a safe circular buffer receiver
> transmitter? It's for sending and receiving bytes via RS232.
/
*--------------------------------------------------------------------------
* Filename: queue.h
*
* Description: Generic circular queue macros
*
* Notes
*
* The queue macros are safe when used in producer/consumer fashion.
* User must check queue full/empty conditions prior to enqueuing/
* dequeueing.
*
* Example Usage
*
* #include "queue.h"
*
* #define MY_Q_SIZE 10
*
* struct
* {
* queue_hdr_t hdr; // must be named
"hdr"
* my_type_t items[MY_Q_SIZE+1]; // must be named "items", 1
space wasted
* } my_q;
*
* my_type_t an_item;
*
* QUEUE_INIT(my_q);
*
* if (!QUEUE_FULL(q))
* {
* QUEUE_PUT(my_q,an_item);
* }
*
* if (!QUEUE_EMPTY(q))
* {
* QUEUE_GET(my_q,an_item);
* }
*
--------------------------------------------------------------------------
*/
#ifndef __QUEUE_H__
#define __QUEUE_H__
/*-------------------------------- Includes
--------------------------------*/
#include "types.h"
/*---------------------------- Defines & Types
-----------------------------*/
#define QUEUE_INIT(q) \
q.hdr.front = q.hdr.rear = 0; \
q.hdr.size = sizeof(q.items) / sizeof(q.items[0]);
#define QUEUE_PUT(q,item) \
q.items[q.hdr.rear] = item; \
q.hdr.rear = (q.hdr.rear+1) % q.hdr.size;
#define QUEUE_GET(q,item) \
item = q.items[q.hdr.front]; \
q.hdr.front = (q.hdr.front + 1) % q.hdr.size;
#define QUEUE_FRONT(q,item) \
item = q.items[q.hdr.front]
#define QUEUE_EMPTY(q) (q.hdr.front == q.hdr.rear)
#define QUEUE_FULL(q) ((q.hdr.rear + 1) % q.hdr.size == q.hdr.front)
/* Private - do not access directly */
typedef struct
{
int front;
int rear;
int size;
} queue_hdr_t;
/*---------------------------- Global Variables
----------------------------*/
/*--------------------------- Function Prototypes
--------------------------*/
#endif
Reply by Mark Borgerson●August 30, 20072007-08-30
In article <46d572d6$0$90271$14726298@news.sunsite.dk>, Sven@tim.com
says...
> Can someone point out source code for a safe circular buffer receiver
> transmitter? It's for sending and receiving bytes via RS232.
>
>
You can find source code for a library using queues and interrupts
to receive UART data on a 68K system at:
http://www.oes.to/u4scfxlib.zip
It may not be the best code out there, but I haven't had
to make any major changes in about 5 years now, and my
customers indicate that it does the job for them.
If you have particular questions, send me an email.
Mark Borgerson
Reply by Stefan Reuther●August 30, 20072007-08-30
Dave Hansen wrote:
> On Aug 29, 11:54 am, Stefan Reuther <stefan.n...@arcor.de> wrote:
>>cs_post...@hotmail.com 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
Signal Processing Engineer Seeking a DSP Engineer to tackle complex technical challenges. Requires expertise in DSP algorithms, EW, anti-jam, and datalink vulnerability. Qualifications: Bachelor's degree, Secret Clearance, and proficiency in waveform modulation, LPD waveforms, signal detection, MATLAB, algorithm development, RF, data links, and EW systems. The position is on-site in Huntsville, AL and can support candidates at 3+ or 10+ years of experience.