ringbuffer.c
3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include "ringbuffer.h"
#include "string.h"
#ifdef FREERTOS
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#include "semphr.h"
#include "portmacro.h"
xSemaphoreHandle xSemaphore_RINGBUF = NULL;
#endif
#define WRITE_SUCCEED 0
#define READ_SUCCESS 0
#define FAIL_LACK_OF_SPACE -1
#define FAIL_READ_TOO_FAST -2
static uint16_t WRITE_ID;
static uint16_t READ_ID;
static uint16_t BUF_LEN;
static uint8_t *RING_BUFFER;
uint16_t RingBuffer_everMAX = 0;
/***************************RINGBUF_SEND***************************/
/*
*warning:this API is not safe for interrupt operation,please ensure only one IRQ functions call this function.
*/
int8_t RINGBUF_SEND(const char *buffer,uint16_t len)
{
if(len > RINGBUF_AVALIABLE_SPACE())
{
return FAIL_LACK_OF_SPACE;
}
uint16_t distance = BUF_LEN - WRITE_ID;
if(distance>len)
{
memcpy((void *)&RING_BUFFER[WRITE_ID],buffer,len);
WRITE_ID += len;
}
else
{
memcpy((void *)&RING_BUFFER[WRITE_ID],buffer,distance);
WRITE_ID = 0;
if(len-distance)
{
memcpy((void *)&RING_BUFFER[WRITE_ID],buffer+distance,len-distance);
WRITE_ID = len-distance;
}
}
(WRITE_ID+BUF_LEN-READ_ID)%BUF_LEN > RingBuffer_everMAX ? RingBuffer_everMAX = (WRITE_ID+BUF_LEN-READ_ID)%BUF_LEN : 1;
return WRITE_SUCCEED;
}
/***************************RINGBUF_READ***************************/
int8_t RINGBUF_READ(uint8_t *buffer,uint16_t len)
{
#ifdef FREERTOS
xSemaphoreTake( xSemaphore_RINGBUF, portMAX_DELAY );//take Mutex for read
#endif
if(len > (BUF_LEN - RINGBUF_AVALIABLE_SPACE()))
{
#ifdef FREERTOS
xSemaphoreGive( xSemaphore_RINGBUF );
#endif
return FAIL_READ_TOO_FAST;
}
uint16_t distance = BUF_LEN - READ_ID;
if(distance>len)
{
memcpy((void *)buffer,&RING_BUFFER[READ_ID],len);
READ_ID += len;
}
else
{
memcpy((void *)buffer,&RING_BUFFER[READ_ID],distance);
READ_ID = 0;
if(len-distance)
{
memcpy((void *)(buffer+distance),&RING_BUFFER[READ_ID],len-distance);
READ_ID = len-distance;
}
}
*(buffer+len) = NULL;
#ifdef FREERTOS
xSemaphoreGive( xSemaphore_RINGBUF );//give Mutex for read
#endif
return READ_SUCCESS;
}
/***************************RINGBUF_PEEK***************************/
int8_t RINGBUF_PEEK(uint8_t *buffer,uint16_t len)
{
#ifdef FREERTOS
xSemaphoreTake( xSemaphore_RINGBUF, portMAX_DELAY );//take Mutex for read
#endif
if(len > (BUF_LEN - RINGBUF_AVALIABLE_SPACE()))
{
#ifdef FREERTOS
xSemaphoreGive( xSemaphore_RINGBUF );
#endif
return FAIL_READ_TOO_FAST;
}
uint16_t readpoint = READ_ID;
uint16_t distance = BUF_LEN - readpoint;
if(distance>len)
{
memcpy((void *)buffer,&RING_BUFFER[readpoint],len);
readpoint += len;
}
else
{
memcpy((void *)buffer,&RING_BUFFER[readpoint],distance);
readpoint = 0;
if(len-distance)
{
memcpy((void *)(buffer+distance),&RING_BUFFER[readpoint],len-distance);
readpoint = len-distance;
}
}
*(buffer+len) = NULL;
#ifdef FREERTOS
xSemaphoreGive( xSemaphore_RINGBUF );
#endif
return READ_SUCCESS;
}
/***************************RINGBUF_INIT***************************/
void RINGBUF_INIT(uint8_t * ringbuffer,uint16_t len)
{
#ifdef FREERTOS
xSemaphore_RINGBUF = xSemaphoreCreateMutex();
#endif
WRITE_ID = 0;
READ_ID = 0;
RING_BUFFER = ringbuffer;
BUF_LEN = len;
memset(RING_BUFFER,0x00,BUF_LEN);
}
/***************************RINGBUF_CHECKIO************************/
uint8_t RINGBUF_CHECKIO(void)
{
if(READ_ID == WRITE_ID)
return 0;
else
return 1;
}
/****************************RINGBUF_AVALIABLE_SPACE***************/
uint16_t RINGBUF_AVALIABLE_SPACE()
{
uint16_t len = 0;
if(WRITE_ID < READ_ID)
{
len = READ_ID - WRITE_ID;
}
else
{
len = BUF_LEN - (WRITE_ID - READ_ID);
}
return len;
}