2014-03-05 24 views
1

我在我的系统中使用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

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

我不得不修改他们一点得到我想要的东西,但作为一个平台的基础上,它是坚如磐石。

我已经用intint32_t<stdint.h>等取代,以确保我有一个可移植的实现。除此之外,我认为我没有太大变化。 我使用各种不同的字大小不同处理器的代码,字节顺序等只是工作(TM):)

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

+0

我不想在运行时做到这一点。现在我的实现只使用静态内存,我想保持这种方式。我想避免动态分配。我现在在应用程序中使用堆,但我正在谨慎地做。我把这个注释放在避免提出“只是将指针放入动态内存,在启动时获取malloc”的提示。 – Nick

+0

好的,我正在查看你链接的这个实现。它看起来与我的工作方式几乎完全一样,只是数据是从管理结构(ringbuf结构)中分别声明的,并且只有指向该数据的指针在管理结构中定义。我认为这对我来说可以很好地工作。 – Nick

+0

@Nick编写一个在模块中声明的'struct'上运行的模块,是获取对象定位的常见方式 - 就像抽象和封装:) –

相关问题