Piconomic Logo www.piconomic.co.za

ring_buffer.h : FIFO ring buffer
[/general : General utility files & modules]

A data structure that uses a single, fixed-size buffer as if it were connected end-to-end (circular). More...

Data Structures

struct  ring_buffer_t
 Ring buffer structure. More...

Functions

void ring_buffer_init (ring_buffer_t *ring_buffer, u8_t *buffer, size_t buffer_size)
 Initialize the ring buffer.
bool_t ring_buffer_empty (ring_buffer_t *ring_buffer)
 See if the ring buffer is empty.
bool_t ring_buffer_full (ring_buffer_t *ring_buffer)
 See if the ring buffer is full.
bool_t ring_buffer_write_byte (ring_buffer_t *ring_buffer, const u8_t data)
 Write (store) a byte in the ring buffer.
u16_t ring_buffer_write_data (ring_buffer_t *ring_buffer, const u8_t *data, u16_t bytes_to_write)
 Write (store) data in the ring buffer.
bool_t ring_buffer_read_byte (ring_buffer_t *ring_buffer, u8_t *data)
 Read (retrieve) a byte from the ring buffer.
u16_t ring_buffer_read_data (ring_buffer_t *ring_buffer, u8_t *data, u16_t bytes_to_read)
 Read (retrieve) data from the ring buffer.

Detailed Description

Files: ring_buffer.h & ring_buffer.c

A fixed-sized buffer is managed as a FIFO buffer with a "zero-copy" policy, i.e. data is not shifted (copied) when data is removed or added to the buffer. If more data is written to the buffer than there is space for, it is ignored/discarded; no buffer overflow vulnerability.

In this implementation, the maximum amount of bytes that can be stored is one less than the size of the fixed-size buffer, e.g. if the buffer size is 8 bytes, then a maximum of 7 bytes can be stored.

See also:
http://en.wikipedia.org/wiki/Circular_buffer

Graphical examples:

  Buffer is empty:
  
   start       head     end
   |           |        |
  [ ][ ][ ][ ][ ][ ][ ][ ]
               |
               tail
  
  One byte is written to the buffer ('1'):
  
                  head
                  |
  [ ][ ][ ][ ][1][ ][ ][ ]
               |
               tail
  
  One byte is read ('1'); buffer is empty again:
 
                  head
                  |
  [ ][ ][ ][ ][ ][ ][ ][ ]
                  |
                  tail
  
  5 bytes are written ('2','3','4','5','6'); buffer wraps:
  
         head
         |
  [5][6][ ][ ][ ][2][3][4]
                  |
                  tail
  
  2 bytes are written ('7','8'); buffer is full:
  
               head
               |
  [5][6][7][8][ ][2][3][4]
                  |
                  tail

Function Documentation

void ring_buffer_init ( ring_buffer_t ring_buffer,
u8_t buffer,
size_t  buffer_size 
)
Parameters:
ring_buffer Pointer to the ring buffer object
buffer Fixed-size data buffer
buffer_size Fixed-size data buffer size

Definition at line 58 of file ring_buffer.c.

References ring_buffer_t::end, ring_buffer_t::head, ring_buffer_t::start, and ring_buffer_t::tail.

Referenced by uart1_init(), uart2_init(), usart0_init(), and usart1_init().

00061 {
00062     // Initialise the ring buffer structure to be empty
00063     ring_buffer->start = buffer;
00064     ring_buffer->end   = buffer+(buffer_size-1);
00065     ring_buffer->head  = buffer;
00066     ring_buffer->tail  = buffer;
00067 }

bool_t ring_buffer_empty ( ring_buffer_t ring_buffer  ) 
Parameters:
ring_buffer Pointer to the ring buffer object
Return values:
TRUE buffer is empty
FALSE buffer contains data

Definition at line 69 of file ring_buffer.c.

References ring_buffer_t::head, and ring_buffer_t::tail.

Referenced by uart1_rx_buffer_empty(), uart1_tx_buffer_empty(), uart1_tx_finished(), uart2_rx_buffer_empty(), uart2_tx_buffer_empty(), uart2_tx_finished(), usart0_rx_buffer_empty(), usart0_tx_buffer_empty(), usart0_tx_finished(), usart1_rx_buffer_empty(), usart1_tx_buffer_empty(), and usart1_tx_finished().

00070 {
00071     return (ring_buffer->tail == ring_buffer->head);
00072 }

bool_t ring_buffer_full ( ring_buffer_t ring_buffer  ) 
Parameters:
ring_buffer Pointer to the ring buffer object
Return values:
TRUE buffer is full
FALSE buffer is NOT full

Definition at line 74 of file ring_buffer.c.

References ring_buffer_t::end, ring_buffer_t::head, ring_buffer_t::start, and ring_buffer_t::tail.

Referenced by uart1_tx_buffer_full(), uart2_tx_buffer_full(), usart0_tx_buffer_full(), and usart1_tx_buffer_full().

00075 {
00076     // Calculate next position of in pointer
00077     u8_t *next_pos = ring_buffer->head;
00078     if (next_pos == ring_buffer->end)
00079     {
00080         // Wrap pointer to start of buffer
00081         next_pos = ring_buffer->start;
00082     }
00083     else
00084     {
00085         // Increment pointer
00086         next_pos++;
00087     }
00088 
00089     return(next_pos == ring_buffer->tail);
00090 }

bool_t ring_buffer_write_byte ( ring_buffer_t ring_buffer,
const u8_t  data 
)
Parameters:
ring_buffer Pointer to the ring buffer object
data The byte to store in the ring buffer
Return values:
TRUE Byte has been stored in the ring buffer
FALSE Buffer is full and byte was not stored

Definition at line 92 of file ring_buffer.c.

References ring_buffer_t::end, ring_buffer_t::head, ring_buffer_t::start, and ring_buffer_t::tail.

Referenced by uart1_tx_byte(), uart2_tx_byte(), usart0_tx_byte(), and usart1_tx_byte().

00094 {
00095     // Calculate next position of in pointer
00096     u8_t *next_pos = ring_buffer->head;
00097     if (next_pos == ring_buffer->end)
00098     {
00099         // Wrap pointer to start of buffer
00100         next_pos = ring_buffer->start;
00101     }
00102     else
00103     {
00104         // Increment pointer
00105         next_pos++;
00106     }
00107 
00108     // Make sure buffer is not full
00109     if (next_pos == ring_buffer->tail)
00110     {
00111         // Buffer is full
00112         return FALSE;
00113     }
00114 
00115     // Add data to buffer
00116     *ring_buffer->head = data;
00117 
00118     // Advance pointer
00119     ring_buffer->head = next_pos;
00120 
00121     return TRUE;
00122 }

u16_t ring_buffer_write_data ( ring_buffer_t ring_buffer,
const u8_t data,
u16_t  bytes_to_write 
)
Parameters:
ring_buffer Pointer to the ring buffer object
data Pointer to array of data to be stored in the ring buffer
bytes_to_write Amount of data bytes to be written
Returns:
u16_t The actual number of data bytes stored, which may be less than the number specified, because the buffer is full.

Definition at line 124 of file ring_buffer.c.

References ring_buffer_t::end, ring_buffer_t::head, ring_buffer_t::start, and ring_buffer_t::tail.

Referenced by uart1_tx_data(), uart2_tx_data(), usart0_tx_data(), and usart1_tx_data().

00127 {
00128     u8_t *next_pos;
00129     u16_t bytes_written = 0;    
00130 
00131     while (bytes_to_write)
00132     {
00133         // Calculate next position of in pointer
00134         next_pos = ring_buffer->head;
00135         if (next_pos == ring_buffer->end)
00136         {
00137             // Wrap pointer to start of buffer
00138             next_pos = ring_buffer->start;
00139         }
00140         else
00141         {
00142             // Increment pointer
00143             next_pos++;
00144         }
00145         // Make sure buffer is not full
00146         if (next_pos == ring_buffer->tail)
00147         {
00148             // Buffer is full
00149             break;
00150         }
00151 
00152         // Add data to buffer
00153         *ring_buffer->head = *data++;
00154 
00155         // Advance pointer
00156         ring_buffer->head = next_pos;
00157 
00158         // Next byte
00159         bytes_written++;
00160         bytes_to_write--;
00161     }
00162 
00163     return bytes_written;
00164 }

bool_t ring_buffer_read_byte ( ring_buffer_t ring_buffer,
u8_t data 
)
Parameters:
ring_buffer Pointer to the ring buffer object
data Pointer to location where byte must be stored
Return values:
TRUE Valid byte has been retrieved
FALSE Buffer is empty

Definition at line 166 of file ring_buffer.c.

References ring_buffer_t::end, ring_buffer_t::head, ring_buffer_t::start, and ring_buffer_t::tail.

Referenced by uart1_get_rx_byte(), uart2_get_rx_byte(), usart0_get_rx_byte(), and usart1_get_rx_byte().

00168 {
00169     u8_t *next_pos;
00170 
00171     // See if there is data in the buffer
00172     if (ring_buffer->head == ring_buffer->tail)
00173     {
00174         // Buffer is empty
00175         return FALSE;
00176     }
00177 
00178     // Fetch data
00179     *data = *ring_buffer->tail;
00180 
00181     // Calculate next position of out pointer
00182     next_pos = ring_buffer->tail;
00183     if (next_pos == ring_buffer->end)
00184     {
00185         // Wrap pointer to start of buffer
00186         next_pos = ring_buffer->start;
00187     }
00188     else
00189     {
00190         // Increment pointer
00191         next_pos++;
00192     }
00193 
00194     // Advance pointer
00195     ring_buffer->tail = next_pos;
00196 
00197     return TRUE;
00198 }

u16_t ring_buffer_read_data ( ring_buffer_t ring_buffer,
u8_t data,
u16_t  bytes_to_read 
)
Parameters:
ring_buffer Pointer to the ring buffer object
data Pointer to location where data must be stored
bytes_to_read Number of bytes to retrieve
Returns:
u16_t The actual number of bytes retrieved, which may be less than the number specified, because the buffer is empty.

Definition at line 200 of file ring_buffer.c.

References ring_buffer_t::end, ring_buffer_t::head, ring_buffer_t::start, and ring_buffer_t::tail.

Referenced by uart1_get_rx_data(), uart2_get_rx_data(), usart0_get_rx_data(), and usart1_get_rx_data().

00203 {
00204     u8_t  *next_pos;
00205     u16_t bytes_read = 0;    
00206 
00207     while (bytes_to_read)
00208     {
00209         // See if there is data in the buffer
00210         if (ring_buffer->head == ring_buffer->tail)
00211         {
00212             // Buffer is empty
00213             break;
00214         }
00215         // Fetch data
00216         *data++ = *ring_buffer->tail;
00217 
00218         // Calculate next position
00219         next_pos = ring_buffer->tail;
00220         if (next_pos == ring_buffer->end)
00221         {
00222             // Wrap pointer to start of buffer
00223             next_pos = ring_buffer->start;
00224         }
00225         else
00226         {
00227             // Increment pointer
00228             next_pos++;
00229         }
00230 
00231         // Advance pointer
00232         ring_buffer->tail = next_pos;
00233 
00234         // Next byte
00235         bytes_read++;
00236         bytes_to_read--;
00237     }
00238 
00239     return bytes_read;
00240 }

Generated on Fri Aug 13 16:50:38 2010 for Piconomic Firmware Library by doxygen 1.6.3