Skip to content

Commit a532412

Browse files
committed
[VirtIO] Add ringbuffer
1 parent b02c6c6 commit a532412

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/**
2+
* MIT License:
3+
* Copyright (c) 2019 Bumsik kim <k.bumsik@gmail.com>
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
#ifdef VIRTIOCON
24+
25+
#include "ringbuffer.h"
26+
#include <string.h>
27+
#include "wiring.h"
28+
29+
#define BUFFER_END (VIRTIO_RINGBUFFER_SIZE - 1)
30+
31+
static uint16_t read_tmp(ringbuffer_t *ring, uint8_t *dst, uint16_t size);
32+
static void read_commit(ringbuffer_t *ring);
33+
static void read_rollback(ringbuffer_t *ring);
34+
35+
void ringbuffer_init(ringbuffer_t *ring)
36+
{
37+
ring->write = 0;
38+
ring->read = 0;
39+
ring->read_tmp = 0;
40+
}
41+
42+
uint16_t ringbuffer_read_available(ringbuffer_t *ring)
43+
{
44+
// This will make the function safe when write openrations are done in interrupts
45+
volatile uint16_t write = ring->write;
46+
47+
if (write < ring->read) {
48+
return (BUFFER_END - ring->read) + (write + 1);
49+
}
50+
return write - ring->read;
51+
}
52+
53+
static uint16_t read_tmp(ringbuffer_t *ring, uint8_t *dst, uint16_t size)
54+
{
55+
// This will make the function safe when write openrations are done in interrupts
56+
volatile uint16_t write = ring->write;
57+
uint16_t end = (write >= ring->read_tmp) ? write : BUFFER_END + 1;
58+
59+
size = min(end - ring->read_tmp, size);
60+
memcpy(dst, ring->buffer + ring->read_tmp, size);
61+
ring->read_tmp += size;
62+
if (ring->read_tmp > BUFFER_END) {
63+
ring->read_tmp = 0;
64+
}
65+
return size;
66+
}
67+
68+
static void read_commit(ringbuffer_t *ring)
69+
{
70+
ring->read = ring->read_tmp;
71+
}
72+
73+
static void read_rollback(ringbuffer_t *ring)
74+
{
75+
ring->read_tmp = ring->read;
76+
}
77+
78+
uint16_t ringbuffer_read(ringbuffer_t *ring, uint8_t *dst, uint16_t size)
79+
{
80+
uint16_t recv_size = read_tmp(ring, dst, size);
81+
read_commit(ring);
82+
return recv_size;
83+
}
84+
85+
/**
86+
* WARNING: The size of read cannot be larger than ringbuffer_read_available().
87+
*/
88+
uint16_t ringbuffer_peek(ringbuffer_t *ring, uint8_t *dst, uint16_t size)
89+
{
90+
size = min(size, ringbuffer_read_available(ring));
91+
uint16_t recv_size = 0;
92+
while (recv_size < size) {
93+
recv_size += read_tmp(ring, dst + recv_size, size - recv_size);
94+
}
95+
read_rollback(ring);
96+
return recv_size;
97+
}
98+
99+
uint16_t ringbuffer_write_available(ringbuffer_t *ring)
100+
{
101+
// This will make the function safe when read openrations are done in interrupts
102+
volatile uint16_t read = ring->read;
103+
104+
if (ring->write < read) {
105+
return (read - 1) - ring->write;
106+
}
107+
return read + (BUFFER_END - ring->write);
108+
}
109+
110+
uint16_t ringbuffer_write(ringbuffer_t *ring, uint8_t *src, uint16_t size)
111+
{
112+
// This will make the function safe when read openrations are done in a interrupt
113+
volatile uint16_t read = ring->read;
114+
uint16_t end = (ring->write < read) ? read - 1
115+
: (read == 0) ? BUFFER_END : BUFFER_END + 1;
116+
117+
size = min(end - ring->write, size);
118+
memcpy(ring->buffer + ring->write, src, size);
119+
ring->write += size;
120+
if (ring->write > BUFFER_END) {
121+
ring->write = 0;
122+
}
123+
return size;
124+
}
125+
126+
#endif /* VIRTIOCON */
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* MIT License:
3+
* Copyright (c) 2019 Bumsik kim <k.bumsik@gmail.com>
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
24+
#ifndef __VIRTIO_RINGBUFFER_H
25+
#define __VIRTIO_RINGBUFFER_H
26+
27+
#include <stdint.h>
28+
29+
#ifdef __cplusplus
30+
extern "C" {
31+
#endif
32+
33+
#ifndef RPMSG_BUFFER_SIZE
34+
#error "Define RPMSG_BUFFER_SIZE, or include relevant headers."
35+
#endif
36+
37+
#define VIRTIO_RINGBUFFER_SIZE (RPMSG_BUFFER_SIZE * 2)
38+
39+
typedef struct {
40+
uint8_t buffer[VIRTIO_RINGBUFFER_SIZE];
41+
volatile uint16_t write;
42+
volatile uint16_t read;
43+
volatile uint16_t read_tmp;
44+
} ringbuffer_t;
45+
46+
void ringbuffer_init(ringbuffer_t *ring);
47+
48+
uint16_t ringbuffer_read_available(ringbuffer_t *ring);
49+
uint16_t ringbuffer_read(ringbuffer_t *ring, uint8_t *dst, uint16_t size);
50+
uint16_t ringbuffer_peek(ringbuffer_t *ring, uint8_t *dst, uint16_t size);
51+
52+
uint16_t ringbuffer_write_available(ringbuffer_t *ring);
53+
uint16_t ringbuffer_write(ringbuffer_t *ring, uint8_t *src, uint16_t size);
54+
55+
#ifdef __cplusplus
56+
}
57+
#endif
58+
59+
#endif // __VIRTIO_RINGBUFFER_H

0 commit comments

Comments
 (0)