1010 * 2016-08-18 heyuanjie add interface
1111 * 2021-07-20 arminker fix write_index bug in function rt_ringbuffer_put_force
1212 * 2021-08-14 Jackistang add comments for function interface.
13+ * 2026-03-16 RyanCW(Codex) fix put_force overwrite in wrapped state
1314 */
1415
1516#include <rtdevice.h>
@@ -39,7 +40,8 @@ void rt_ringbuffer_init(struct rt_ringbuffer *rb,
3940 rt_int32_t size )
4041{
4142 RT_ASSERT (rb != RT_NULL );
42- RT_ASSERT (size > 0 );
43+ RT_ASSERT (pool != RT_NULL );
44+ RT_ASSERT (size >= RT_ALIGN_SIZE );
4345
4446 /* initialize read and write index */
4547 rb -> read_mirror = rb -> read_index = 0 ;
@@ -67,6 +69,9 @@ rt_size_t rt_ringbuffer_put(struct rt_ringbuffer *rb,
6769 rt_uint32_t size ;
6870
6971 RT_ASSERT (rb != RT_NULL );
72+ if (length == 0 )
73+ return 0 ;
74+ RT_ASSERT (ptr != RT_NULL );
7075
7176 /* whether has enough space */
7277 size = rt_ringbuffer_space_len (rb );
@@ -118,49 +123,71 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb,
118123 rt_uint32_t length )
119124{
120125 rt_uint32_t space_length ;
126+ rt_uint32_t drop_length ;
121127
122128 RT_ASSERT (rb != RT_NULL );
123129
124- space_length = rt_ringbuffer_space_len (rb );
130+ if (length == 0 )
131+ return 0 ;
132+ RT_ASSERT (ptr != RT_NULL );
125133
134+ /* Oversize write keeps the latest bytes. */
126135 if (length > rb -> buffer_size )
127136 {
128137 ptr = & ptr [length - rb -> buffer_size ];
129138 length = rb -> buffer_size ;
130139 }
131140
141+ space_length = rt_ringbuffer_space_len (rb );
142+
143+ rt_bool_t overflow = (length > space_length );
144+
145+ if (overflow )
146+ {
147+ /* Drop the oldest bytes to make room for the incoming data. */
148+ drop_length = length - space_length ;
149+ if (rb -> buffer_size - rb -> read_index > drop_length )
150+ {
151+ rb -> read_index += drop_length ;
152+ }
153+ else
154+ {
155+ drop_length -= (rb -> buffer_size - rb -> read_index );
156+ rb -> read_index = drop_length ;
157+ /* Read pointer wraps to the other side of the mirror. */
158+ rb -> read_mirror = ~rb -> read_mirror ;
159+ }
160+ }
161+
132162 if (rb -> buffer_size - rb -> write_index > length )
133163 {
134164 /* read_index - write_index = empty space */
135165 rt_memcpy (& rb -> buffer_ptr [rb -> write_index ], ptr , length );
136166 /* this should not cause overflow because there is enough space for
137167 * length of data in current mirror */
138168 rb -> write_index += length ;
139-
140- if (length > space_length )
141- rb -> read_index = rb -> write_index ;
142-
143- return length ;
144169 }
170+ else
171+ {
172+ rt_uint32_t tail = rb -> buffer_size - rb -> write_index ;
145173
146- rt_memcpy (& rb -> buffer_ptr [rb -> write_index ],
147- & ptr [0 ],
148- rb -> buffer_size - rb -> write_index );
149- rt_memcpy (& rb -> buffer_ptr [0 ],
150- & ptr [rb -> buffer_size - rb -> write_index ],
151- length - (rb -> buffer_size - rb -> write_index ));
152-
153- /* we are going into the other side of the mirror */
154- rb -> write_mirror = ~rb -> write_mirror ;
155- rb -> write_index = length - (rb -> buffer_size - rb -> write_index );
174+ rt_memcpy (& rb -> buffer_ptr [rb -> write_index ], ptr , tail );
175+ rt_memcpy (& rb -> buffer_ptr [0 ], & ptr [tail ], length - tail );
156176
157- if (length > space_length )
158- {
159- if (rb -> write_index <= rb -> read_index )
160- rb -> read_mirror = ~rb -> read_mirror ;
161- rb -> read_index = rb -> write_index ;
177+ /* we are going into the other side of the mirror */
178+ rb -> write_mirror = ~rb -> write_mirror ;
179+ rb -> write_index = length - tail ;
162180 }
163181
182+ /*
183+ * If we dropped data and write catches up to read, we must keep
184+ * "full" distinct from "empty" by flipping the write mirror.
185+ */
186+ if (overflow &&
187+ (rb -> write_index == rb -> read_index ) &&
188+ (rb -> write_mirror == rb -> read_mirror ))
189+ rb -> write_mirror = ~rb -> write_mirror ;
190+
164191 return length ;
165192}
166193RTM_EXPORT (rt_ringbuffer_put_force );
@@ -181,6 +208,9 @@ rt_size_t rt_ringbuffer_get(struct rt_ringbuffer *rb,
181208 rt_size_t size ;
182209
183210 RT_ASSERT (rb != RT_NULL );
211+ if (length == 0 )
212+ return 0 ;
213+ RT_ASSERT (ptr != RT_NULL );
184214
185215 /* whether has enough data */
186216 size = rt_ringbuffer_data_len (rb );
@@ -235,6 +265,7 @@ rt_size_t rt_ringbuffer_get_direct(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
235265 rt_size_t size ;
236266
237267 RT_ASSERT (rb != RT_NULL );
268+ RT_ASSERT (ptr != RT_NULL );
238269
239270 * ptr = RT_NULL ;
240271
@@ -278,6 +309,7 @@ rt_size_t rt_ringbuffer_peek(struct rt_ringbuffer *rb, rt_uint8_t **ptr)
278309 rt_size_t size ;
279310
280311 RT_ASSERT (rb != RT_NULL );
312+ RT_ASSERT (ptr != RT_NULL );
281313
282314 * ptr = RT_NULL ;
283315
@@ -386,6 +418,7 @@ RTM_EXPORT(rt_ringbuffer_putchar_force);
386418rt_size_t rt_ringbuffer_getchar (struct rt_ringbuffer * rb , rt_uint8_t * ch )
387419{
388420 RT_ASSERT (rb != RT_NULL );
421+ RT_ASSERT (ch != RT_NULL );
389422
390423 /* ringbuffer is empty */
391424 if (!rt_ringbuffer_data_len (rb ))
@@ -417,6 +450,8 @@ RTM_EXPORT(rt_ringbuffer_getchar);
417450 */
418451rt_size_t rt_ringbuffer_data_len (struct rt_ringbuffer * rb )
419452{
453+ RT_ASSERT (rb != RT_NULL );
454+
420455 switch (rt_ringbuffer_status (rb ))
421456 {
422457 case RT_RINGBUFFER_EMPTY :
@@ -467,7 +502,7 @@ struct rt_ringbuffer *rt_ringbuffer_create(rt_uint32_t size)
467502 struct rt_ringbuffer * rb ;
468503 rt_uint8_t * pool ;
469504
470- RT_ASSERT (size > 0 );
505+ RT_ASSERT (size >= RT_ALIGN_SIZE );
471506
472507 size = RT_ALIGN_DOWN (size , RT_ALIGN_SIZE );
473508
0 commit comments