大家好,周末快樂,我是小麥,今天分享一下CBUF。
循環緩沖區是嵌入式軟件工程師在日常開發過程中的關鍵組件。
多年來,互聯網上出現了許多不同的循環緩沖區實現和示例。我非常喜歡這個模塊,可以GitHub上找到這個開源的 CBUF.h 模塊。
地址:https://github.com/barraq/BRBrain/blob/master/firmware/CBUF.h
CBUF.h 模塊使用宏實現循環緩沖區,具體源碼如下所示;
#if !defined( CBUF_H )#define CBUF_H /**《 Include Guard *//* ---- Include Files ---------------------------------------------------- *//* ---- Constants and Types ---------------------------------------------- *//**
* Initializes the circular buffer for use.
*/
#define CBUF_Init( cbuf ) cbuf.m_getIdx = cbuf.m_putIdx = 0/**
* Returns the number of elements which are currently contained in the
* circular buffer.
*/#define CBUF_Len( cbuf ) ((typeof( cbuf.m_putIdx ))(( cbuf.m_putIdx ) - ( cbuf.m_getIdx )))/**
* Appends an element to the end of the circular buffer
*/#define CBUF_Push( cbuf, elem ) (cbuf.m_entry)[ cbuf.m_putIdx++ & (( cbuf##_SIZE ) - 1 )] = (elem)/**
* Retrieves an element from the beginning of the circular buffer
*/#define CBUF_Pop( cbuf ) (cbuf.m_entry)[ cbuf.m_getIdx++ & (( cbuf##_SIZE ) - 1 )]/**
* Retrieves the i‘th element from the beginning of the circular buffer
*/#define CBUF_Get( cbuf, idx ) (cbuf.m_entry)[( cbuf.m_getIdx + idx ) & (( cbuf##_SIZE ) - 1 )]/**
* Retrieves the i’th element from the end of the circular buffer
*/#define CBUF_GetEnd( cbuf, idx ) (cbuf.m_entry)[( cbuf.m_putIdx - idx - 1 ) & (( cbuf##_SIZE ) - 1 )]/**
* Determines if the circular buffer is empty
*/#define CBUF_IsEmpty( cbuf ) ( CBUF_Len( cbuf ) == 0 )/**
* Determines if the circular buffer is full.
*/#define CBUF_IsFull( cbuf ) ( CBUF_Len( cbuf ) == ( cbuf##_SIZE ))/**
* Determines if the circular buffer is currenly overflowed or underflowed.
*/#define CBUF_Error( cbuf ) ( CBUF_Len( cbuf ) 》 cbuf##_SIZE )#if defined( __cplusplus )template 《 class IndexType, unsigned Size, class EntryType 》
class CBUF
{public:
CBUF()
{
m_getIdx = m_putIdx = 0;
}
IndexType Len() const { return m_putIdx - m_getIdx; }
bool IsEmpty() const { return Len() == 0; }
bool IsFull() const { return Len() == Size; }
bool Error() const { return Len() 》 Size; }
void Push( EntryType val )
{
m_entry[ m_putIdx++ & ( Size - 1 )] = val;
}
EntryType Pop()
{
return m_entry[ m_getIdx++ & ( Size - 1 )];
}
private:
volatile IndexType m_getIdx;
volatile IndexType m_putIdx;
EntryType m_entry[ Size ];
};
#endif // __cplusplus/* ---- Variable Externs ------------------------------------------------- *//* ---- Function Prototypes ---------------------------------------------- *//** @} */#endif // CBUF_H
現在一般我不喜歡以這種方式使用宏,但實現已被證明是快速、高效且工作相對良好的,這是很難爭論的。
循環緩沖區的設置非常簡單。首先,需要定義循環緩沖區的大小。這是通過定義宏 myQ_SIZE 來完成的,同時記住緩沖區大小需要是 2 的冪。
然后通過創建一個 myQ 類型的變量來聲明循環緩沖區。例如,如果 myQ_SIZE 定義為 64 字節,則可以定義 UART 的發送和接收緩沖區,如下面的圖 1 所示。
圖 1 – 定義循環緩沖區
在此示例中,myQ 被定義為靜態以限制緩沖區的范圍并聲明為易失性,因為它們在中斷內被修改。定義循環緩沖區只是第一步。為了分配緩沖區,必須將這些變量傳遞給 CBUF_INIT 宏,如下圖 2 所示。
圖 2 – 緩沖區初始化
除了這個初始設置之外,緩沖區相當簡單且易于使用。例如,可以使用 CBUF_PUSH 將通過串行接口接收 UART接收的字符推送到循環緩沖區,如圖 3 所示。
圖 3 – 推入緩沖區
開發人員不僅希望將數據推送到循環緩沖區上,還希望從緩沖區彈出或獲取數據。看到這一點的一個簡單示例是需要獲取字符并通過 UART 傳輸的串行發送器。圖 4 中可以看到一個示例傳輸函數。
圖 4 – 從緩沖區彈出數據
在健壯的應用程序中,還應檢查循環緩沖區長度和溢出狀態。CBUF 模塊確實提供了能夠檢查這些重要指標的宏。
要記住的一個重要問題是,如果需要對 CBUF 本身進行任何調試,這是不可能的。無法為宏設置斷點,因此如果出現問題,則需要對模塊進行功能化以逐步執行和調試。
多年來使用這個模塊雖然我沒有發現任何問題。循環緩沖區是在嵌入式系統中與串行設備通信的一個重要方面。
循環緩沖區也很好理解,應該創建它們以便它們可以模塊化并從一個應用程序到下一個應用程序重復使用。
到目前為止,CBUF 模塊已被證明是這樣一個模塊,所以在這里,我強烈推薦一下這個模塊。好了,今天的文章就到這里,我們下期再見。
責任編輯:haq
-
模塊
+關注
關注
7文章
2716瀏覽量
47543 -
嵌入式
+關注
關注
5086文章
19140瀏覽量
305879
原文標題:優雅地用宏實現環形緩沖區
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論