EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Serial driver implementation questions

Started by joshc August 6, 2006
I'm implementing a serial transmit driver for a micro that isn't
running an RTOS and I have some form of an implementation working but
I'd like some advice on it. Just a note, the function "getc" is a bit
confusing here because it isn't for received characters but rather is a
way for the UART empty ISR to get characters to send out. Here's the
pseudocode for my implementation:

char txBuffer[BUF_SIZE];
int head;
int tail;
bool empty;

int putc(char c) {
if no transmission in progress AND empty is TRUE //don't buffer
    directly write to transmit register;
else {
  if head == tail AND empty is FALSE // txBuffer full
      return error;
  else {
      empty = FALSE;
      txBuffer[head++] = c;
      txBuffer %= BUF_SIZE;
}

}

int getc(void) {
if empty == TRUE
  return error;
else {
  ret_val = txBuffer[tail++];
  tail %= BUF_SIZE;
  if tail == head
    empty = TRUE;

  return ret_val;
}

}

I want some advice on where I need some sort of synchronization
primitives in this implementation. I am disabling interrupts at several
points in both the putc() and getc() functions because both are
interruptible. getc() is called from the UART empty ISR so that I can
send the next character out for transmission. Any advice on where the
critical sections are and any other advice on this implementation?

I read somewhere that you can come up with an implementation of a
circular buffer that doesn't need synchronization by having one wasted
spot in the buffer. How would this be implemented? I don't see how this
would eliminate the need for synchronization.

I appreciate any help.

joshc wrote:
> I'm implementing a serial transmit driver for a micro that isn't > running an RTOS and I have some form of an implementation working but > I'd like some advice on it. Just a note, the function "getc" is a bit
I like to use a buffered_bytes_counter because it allows sanity checks. It should: -never be less than 0 -never be more than BUFSIZE -either be wr_ptr-rd_ptr (if wr_ptr > rd_ptr) BUFSIZE + wr_ptr - rd_ptr (if wr_ptr < rd_ptr) You also need the empty flag to see if the special case of wr_ptr=rd_ptr means the buffer is empty or full. Well, something like this anyway..
On Sat, 05 Aug 2006 21:02:08 -0700, joshc wrote:

 I read somewhere that you can come up with an implementation of a
> circular buffer that doesn't need synchronization by having one wasted > spot in the buffer. How would this be implemented? I don't see how this > would eliminate the need for synchronization.
Single-reader single-writer. Google "single reader+synchronization" or see http://www.audiomulch.com/~rossb/code/lockfree for one reference. ~Dave~

Memfault Beyond the Launch