我需要一个环形缓冲区(用C语言编写),该缓冲区可以在运行时保存任何类型的对象(几乎数据将是不同的信号值,例如电流(100ms和10ms)和温度等)(我不确定它是否必须是固定大小),并且需要非常高的性能。尽管它是在多任务嵌入式环境中。
实际上,我需要此缓冲区作为备份,这意味着嵌入式软件将正常运行并将数据保存到环形缓冲区中,到目前为止,无论出于何种原因,当发生错误时,我都可以参考测量值,然后我就可以看一下并确定问题所在。另外,我需要在环形缓冲区上做一个时间戳记,这意味着存储在环形缓冲区上的每个数据(信号值)都将与测量时间一起存储。
任何代码或想法都将不胜感激。所需的一些操作是:
创建具有特定大小的环形缓冲区。 将其与整个软件链接。 放在尾巴。 从头上得到。 错误时,读取数据及其发生的时间(时间戳)。 返回计数。 当缓冲区已满时覆盖。
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct ring_buffer
{
void * buffer; // data buffer
void * buffer_end; // end of data buffer
void * data_start; // pointer to head
void * data_end; // pointer to tail
uint64_t capacity; // maximum number of items in buffer
uint64_t count; // number of items in the buffer
uint64_t size; // size of each item in the buffer
} ring_buffer;
void rb_init (ring_buffer *rb, uint64_t size, uint64_t capacity )
{
rb->buffer = malloc(capacity * size);
if(rb->buffer == NULL)
// handle error
rb->buffer_end = (char *)rb->buffer + capacity * size;
rb->capacity = capacity;
rb->count = 0;
rb->size = size;
rb->data_start = rb->buffer;
rb->data_end = rb->buffer;
}
void cb_free(ring_buffer *rb)
{
free(rb->buffer);
// clear out other fields too, just to be safe
}
void rb_push_back(ring_buffer *rb, const void *item)
{
if(rb->count == rb->capacity){
// handle error
}
memcpy(rb->data_start, item, rb->size);
rb->data_start = (char*)rb->data_start + rb->size;
if(rb->data_start == rb->buffer_end)
rb->data_start = rb->buffer;
rb->count++;
}
void rb_pop_front(ring_buffer *rb, void *item)
{
if(rb->count == 0){
// handle error
}
memcpy(item, rb->data_end, rb->size);
rb->data_end = (char*)rb->data_end + rb->size;
if(rb->data_end == rb->buffer_end)
rb->data_end = rb->buffer;
rb->count--;
}
答案 0 :(得分:0)
使用通用类型的硬拷贝创建环形缓冲区/ FIFO对于嵌入式系统而言是非常成问题的设计。如此接近硬件的代码,不需要高级别的抽象。
要么用数据类型标记(如枚举)加void*
的环形缓冲区来分配分配给其他位置的数据,要么制作所有数据都属于同一类型的环形缓冲区。其他所有内容很可能是混淆的程序设计(“ XY问题”)。
您需要一些方法来在内部锁定对环形缓冲区的访问,以使其成为线程安全/中断安全的。这以及时间戳,必须由环形缓冲区ADT在内部进行处理。