update fifo

This commit is contained in:
hathach 2018-02-28 15:23:41 +07:00
parent 45ea2ff358
commit c961bb47fe
2 changed files with 208 additions and 87 deletions

View File

@ -7,7 +7,7 @@
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
Copyright (c) 2018, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -35,18 +35,36 @@
This file is part of the tinyusb stack.
*/
/**************************************************************************/
#include <string.h>
#include "fifo.h"
//static inline void mutex_lock (fifo_t* f) ATTR_ALWAYS_INLINE;
//static inline void mutex_unlock (fifo_t* f) ATTR_ALWAYS_INLINE;
#define mutex_lock(f)
#define mutex_unlock(f)
/*------------------------------------------------------------------*/
/*
*------------------------------------------------------------------*/
#if CFG_FIFO_MUTEX
static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE;
#define mutex_lock_if_needed(_ff) if (_ff->mutex) fifo_mutex_lock(_ff->mutex)
#define mutex_unlock_if_needed(_ff) if (_ff->mutex) fifo_mutex_unlock(_ff->mutex)
#else
#define mutex_lock_if_needed(_ff)
#define mutex_unlock_if_needed(_ff)
#endif
static inline uint16_t min16_of(uint16_t x, uint16_t y)
{
return (x < y) ? x : y;
}
static inline bool fifo_initalized(fifo_t* f)
{
return (f->buffer != NULL) && (f->depth > 0) && (f->item_size > 0);
}
/**************************************************************************/
/******************************************************************************/
/*!
@brief Read one byte out of the RX buffer.
@ -56,20 +74,18 @@ static inline bool is_fifo_initalized(fifo_t* f) ATTR_ALWAYS_INLINE;
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
@param[in] p_buffer
Pointer to the place holder for data read from the buffer
@returns TRUE if the queue is not empty
*/
/**************************************************************************/
/******************************************************************************/
bool fifo_read(fifo_t* f, void * p_buffer)
{
if( !is_fifo_initalized(f) || fifo_is_empty(f) )
{
return false;
}
if( !fifo_initalized(f) ) return false;
if( fifo_is_empty(f) ) return false;
mutex_lock(f);
mutex_lock_if_needed(f);
memcpy(p_buffer,
f->buffer + (f->rd_idx * f->item_size),
@ -77,36 +93,108 @@ bool fifo_read(fifo_t* f, void * p_buffer)
f->rd_idx = (f->rd_idx + 1) % f->depth;
f->count--;
mutex_unlock(f);
mutex_unlock_if_needed(f);
return true;
}
/**************************************************************************/
/******************************************************************************/
/*!
@brief Write one byte into the RX buffer.
This function will write one byte into the array index specified by
@brief This function will read n elements into the array index specified by
the write pointer and increment the write index. If the write index
exceeds the max buffer size, then it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] data
@param[in] p_data
The pointer to data location
@param[in] count
Number of element that buffer can afford
@returns number of bytes read from the FIFO
*/
/******************************************************************************/
uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count)
{
if( !fifo_initalized(f) ) return false;
if( fifo_is_empty(f) ) return false;
/* Limit up to fifo's count */
count = min16_of(count, f->count);
if( count == 0 ) return 0;
mutex_lock_if_needed(f);
/* Could copy up to 2 portions marked as 'x' if queue is wrapped around
* case 1: ....RxxxxW.......
* case 2: xxxxxW....Rxxxxxx
*/
// uint16_t index2upper = min16_of(count, f->count-f->rd_idx);
uint8_t* p_buf = (uint8_t*) p_buffer;
uint16_t len = 0;
while( (len < count) && fifo_read(f, p_buf) )
{
len++;
p_buf += f->item_size;
}
mutex_unlock_if_needed(f);
return len;
}
/******************************************************************************/
/*!
@brief Reads one item without removing it from the FIFO
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] position
Position to read from in the FIFO buffer
@param[in] p_buffer
Pointer to the place holder for data read from the buffer
@returns TRUE if the queue is not empty
*/
/******************************************************************************/
bool fifo_peek_at(fifo_t* f, uint16_t position, void * p_buffer)
{
if ( !fifo_initalized(f) ) return false;
if ( position >= f->count ) return false;
// rd_idx is position=0
uint16_t index = (f->rd_idx + position) % f->depth;
memcpy(p_buffer,
f->buffer + (index * f->item_size),
f->item_size);
return true;
}
/******************************************************************************/
/*!
@brief Write one element into the RX buffer.
This function will write one element into the array index specified by
the write pointer and increment the write index. If the write index
exceeds the max buffer size, then it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] p_data
The byte to add to the FIFO
@returns TRUE if the data was written to the FIFO (overwrittable
FIFO will always return TRUE)
*/
/**************************************************************************/
/******************************************************************************/
bool fifo_write(fifo_t* f, void const * p_data)
{
if ( !is_fifo_initalized(f) || (fifo_is_full(f) && !f->overwritable) )
{
return false;
}
if ( !fifo_initalized(f) ) return false;
if ( fifo_is_full(f) && !f->overwritable ) return false;
mutex_lock(f);
mutex_lock_if_needed(f);
memcpy( f->buffer + (f->wr_idx * f->item_size),
p_data,
@ -117,75 +205,61 @@ bool fifo_write(fifo_t* f, void const * p_data)
if (fifo_is_full(f))
{
f->rd_idx = f->wr_idx; // keep the full state (rd == wr && len = size)
}else
}
else
{
f->count++;
}
mutex_unlock(f);
mutex_unlock_if_needed(f);
return true;
}
/**************************************************************************/
/******************************************************************************/
/*!
@brief This function will write n elements into the array index specified by
the write pointer and increment the write index. If the write index
exceeds the max buffer size, then it will roll over to zero.
@param[in] f
Pointer to the FIFO buffer to manipulate
@param[in] p_data
The pointer to data to add to the FIFO
@param[in] count
Number of element
@return Number of written elements
*/
/******************************************************************************/
uint16_t fifo_write_n(fifo_t* f, void const * p_data, uint16_t count)
{
if ( count == 0 ) return 0;
uint8_t* p_buf = (uint8_t*) p_data;
uint16_t len = 0;
while( (len < count) && fifo_write(f, p_buf) )
{
len++;
p_buf += f->item_size;
}
return len;
}
/******************************************************************************/
/*!
@brief Clear the fifo read and write pointers and set length to zero
@param[in] f
Pointer to the FIFO buffer to manipulate
*/
/**************************************************************************/
/******************************************************************************/
void fifo_clear(fifo_t *f)
{
mutex_lock(f);
mutex_lock_if_needed(f);
f->rd_idx = f->wr_idx = f->count = 0;
mutex_unlock(f);
}
//--------------------------------------------------------------------+
// HELPER FUNCTIONS
//--------------------------------------------------------------------+
/**************************************************************************/
/*!
@brief Disables the IRQ specified in the FIFO's 'irq' field
to prevent reads/write issues with interrupts
@param[in] f
Pointer to the FIFO that should be protected
*/
/**************************************************************************/
//static inline void mutex_lock (fifo_t* f)
//{
// if (f->irq > 0)
// {
// #if !defined (_TEST_)
// NVIC_DisableIRQ(f->irq);
// #endif
// }
//}
/**************************************************************************/
/*!
@brief Re-enables the IRQ specified in the FIFO's 'irq' field
@param[in] f
Pointer to the FIFO that should be protected
*/
/**************************************************************************/
//static inline void mutex_unlock (fifo_t* f)
//{
// if (f->irq > 0)
// {
// #if !defined (_TEST_)
// NVIC_EnableIRQ(f->irq);
// #endif
// }
//}
static inline bool is_fifo_initalized(fifo_t* f)
{
return !( f->buffer == NULL || f->depth == 0 || f->item_size == 0);
mutex_unlock_if_needed(f);
}

View File

@ -7,7 +7,7 @@
Software License Agreement (BSD License)
Copyright (c) 2013, hathach (tinyusb.org)
Copyright (c) 2018, hathach (tinyusb.org)
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -43,12 +43,36 @@
#ifndef _TUSB_FIFO_H_
#define _TUSB_FIFO_H_
#include "common/common.h"
#define CFG_FIFO_MUTEX 0
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#if CFG_FIFO_MUTEX
/*Mutex port for newt*/
#include "os/os_mutex.h"
#define fifo_mutex_t struct os_mutex
#define fifo_mutex_lock(m) os_mutex_pend(m, OS_TIMEOUT_NEVER)
#define fifo_mutex_unlock(m) os_mutex_release(m)
/* Internal use only */
#define _mutex_declare(m) .mutex = m
#else
#define _mutex_declare(m)
#endif
/** \struct fifo_t
* \brief Simple Circular FIFO
*/
@ -61,7 +85,11 @@ typedef struct
volatile uint16_t wr_idx ; ///< write pointer
volatile uint16_t rd_idx ; ///< read pointer
bool overwritable ;
// IRQn_Type irq;
#if CFG_FIFO_MUTEX
fifo_mutex_t * const mutex;
#endif
} fifo_t;
#define FIFO_DEF(name, ff_depth, type, is_overwritable) /*, irq_mutex)*/ \
@ -72,30 +100,49 @@ typedef struct
.item_size = sizeof(type),\
.overwritable = is_overwritable,\
/*.irq = irq_mutex*/\
_mutex_declare(_mutex)\
}
bool fifo_write(fifo_t* f, void const * p_data);
bool fifo_read(fifo_t* f, void * p_buffer);
void fifo_clear(fifo_t *f);
static inline bool fifo_is_empty(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
bool fifo_write (fifo_t* f, void const * p_data);
uint16_t fifo_write_n (fifo_t* f, void const * p_data, uint16_t count);
bool fifo_read (fifo_t* f, void * p_buffer);
uint16_t fifo_read_n (fifo_t* f, void * p_buffer, uint16_t count);
bool fifo_peek_at (fifo_t* f, uint16_t position, void * p_buffer);
static inline bool fifo_peek(fifo_t* f, void * p_buffer)
{
return fifo_peek_at(f, 0, p_buffer);
}
static inline bool fifo_is_empty(fifo_t* f)
{
return (f->count == 0);
}
static inline bool fifo_is_full(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline bool fifo_is_full(fifo_t* f)
{
return (f->count == f->depth);
}
static inline uint16_t fifo_get_length(fifo_t* f) ATTR_PURE ATTR_ALWAYS_INLINE;
static inline uint16_t fifo_get_length(fifo_t* f)
{
return f->count;
}
static inline uint16_t fifo_remaining(fifo_t* f)
{
return f->depth - f->count;
}
static inline uint16_t fifo_depth(fifo_t* f)
{
return f->depth;
}
#ifdef __cplusplus
}
#endif