有关通用队列实现的任何想法,可以在编译时允许可变大小吗?

时间:2014-03-05 16:37:52

标签: c uart msp430

我在我的系统中使用了3种不同的UART。我为RX数据和TX数据定义了一个软件缓冲区。

/*! Queue Size for all UARTS. Defines the size of static memory allocated for
RX and TX Buffers. */
#define QUEUE_SIZE 300u

/*!
* \brief Arbitrary FIFO queue structure used to store RAW serial data
* \ingroup uart
*/
typedef struct
{
   uchar8_t x[QUEUE_SIZE];
   uint16_t head_index;
   uint16_t tail_index;
   uint16_t length;
} serial_queue_t;

我声明了这个结构的6个实例 - 我的每个UART的RX和TX缓冲区。

现在我有一个通用方法从UART中提取字符或将字符推送到UART。

/*!
* \brief Private method used to get and remove the next character in an
* arbitrary UART FIFO queue.
* \ingroup uart
* \param[in] *p_queue The queue to get data from
* \param[out] *p_pull The next character in the buffer. This will not be
* assigned if the character is unavailable.
* \returns TRUE if the next character is available, FALSE if that character is
* not available.
*
* \note This Function is Atomic
* If this function is executing and a UART ISR occurs which would recall this
* function before the tail index has been updated it could cause a memory
* leak/data loss. Therefore this function is not reentrant and must block
* interrupts.
*/
static bool_t uart_pull(serial_queue_t volatile * p_queue, uchar8_t * p_pull);

/*!
* \brief Private method to push a character onto an arbitrary UART queue.
* \ingroup uart
* \param[in,out] *p_queue The queue to push data onto.
* \param[in] push The next character in the buffer. This will not be assigned
* if the character is unavilable.
* \returns TRUE if the character was placed in the queue successfully, FALSE
* if the queue is full.
*
* \note This Function is Atomic
* If this function is executing and a UART ISR occurs which would recall this
* function before the head index has been updated it could cause a memory
* leak/data loss. Therefore this function is not reentrant and must block
* interrupts.
*/
static bool_t uart_push(serial_queue_t volatile * p_queue, uchar8_t push);

现在我需要改变我的实现。我需要调整一些缓冲区的大小以使它们更大,这样我就可以传输更大的数据帧。我还计划缩小一些缓冲区以缩回一些空间,因为300字节对它们来说太过分了。我试图想出一个干净的方法来做到这一点,所以我可以保持我的实现通用。

到目前为止,我最好的想法是简单地定义几个不同的结构,每个不同的数组定义不同的数组,然后使p_queue指针无效。我可以为每个函数添加一个参数,它可以告诉函数使用哪个UART缓冲区,这样它们就可以知道在处理缓冲区时使用哪个结构,或者将另一个字段添加到存储该队列的max_length的队列结构中,并在字符数组前面重新定位max_length,head_index和tail_index。

任何人都有更好的想法 - 因为为几乎相同的事物定义多达6种不同的结构并不是那么干净?我不想将整个事情放在堆上并分配运行时 - 我希望分配在编译时由链接器处理。

1 个答案:

答案 0 :(得分:1)

我正在使用Adam Dunkels ContikiOS的环形缓冲区:http://contiki.sourceforge.net/docs/2.6/a01686.html

我不得不修改它们以获得我想要的东西,但作为一个可以构建的平台,它是坚如磐石的。

我已将int替换为int32_t来自<stdint.h>等,以确保我有可移植的实现。除此之外,我认为我的变化不大。 我在各种不同的处理器上使用该代码,具有不同的字大小,字节序等。它Just Works(TM):)

修改 重新阅读您的问题后,您确定要表示要在编译时而不是运行时更改大小吗? 编译时间很简单,运行时通常意味着动态分配,或者至少是一个带有一些自制分配器的公共内存缓冲区。