ChibiOS/HAL 9.0.0
hal_buffers.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file hal_buffers.c
19 * @brief I/O Buffers code.
20 *
21 * @addtogroup HAL_BUFFERS
22 * @details Buffers Queues are used when there is the need to exchange
23 * fixed-length data buffers between ISRs and threads.
24 * On the ISR side data can be exchanged only using buffers,
25 * on the thread side data can be exchanged both using buffers and/or
26 * using an emulation of regular byte queues.
27 * There are several kind of buffers queues:<br>
28 * - <b>Input queue</b>, unidirectional queue where the writer is the
29 * ISR side and the reader is the thread side.
30 * - <b>Output queue</b>, unidirectional queue where the writer is the
31 * thread side and the reader is the ISR side.
32 * - <b>Full duplex queue</b>, bidirectional queue. Full duplex queues
33 * are implemented by pairing an input queue and an output queue
34 * together.
35 * .
36 * @{
37 */
38
39#include <string.h>
40
41#include "hal.h"
42
43/*===========================================================================*/
44/* Driver local definitions. */
45/*===========================================================================*/
46
47/*===========================================================================*/
48/* Driver exported variables. */
49/*===========================================================================*/
50
51/*===========================================================================*/
52/* Driver local variables and types. */
53/*===========================================================================*/
54
55/*===========================================================================*/
56/* Driver local functions. */
57/*===========================================================================*/
58
59/*===========================================================================*/
60/* Driver exported functions. */
61/*===========================================================================*/
62
63/**
64 * @brief Initializes an input buffers queue object.
65 *
66 * @param[out] ibqp pointer to the @p input_buffers_queue_t object
67 * @param[in] suspended initial state of the queue
68 * @param[in] bp pointer to a memory area allocated for buffers
69 * @param[in] size buffers size
70 * @param[in] n number of buffers
71 * @param[in] infy callback called when a buffer is returned to the queue
72 * @param[in] link application defined pointer
73 *
74 * @init
75 */
76void ibqObjectInit(input_buffers_queue_t *ibqp, bool suspended, uint8_t *bp,
77 size_t size, size_t n, bqnotify_t infy, void *link) {
78
79 osalDbgCheck((ibqp != NULL) && (bp != NULL) && (size >= 2U));
80
82 ibqp->suspended = suspended;
83 ibqp->bcounter = 0;
84 ibqp->brdptr = bp;
85 ibqp->bwrptr = bp;
86 ibqp->btop = bp + ((size + sizeof (size_t)) * n);
87 ibqp->bsize = size + sizeof (size_t);
88 ibqp->bn = n;
89 ibqp->buffers = bp;
90 ibqp->ptr = NULL;
91 ibqp->top = NULL;
92 ibqp->notify = infy;
93 ibqp->link = link;
94}
95
96/**
97 * @brief Resets an input buffers queue.
98 * @details All the data in the input buffers queue is erased and lost, any
99 * waiting thread is resumed with status @p MSG_RESET.
100 * @note A reset operation can be used by a low level driver in order to
101 * obtain immediate attention from the high level layers.
102 *
103 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
104 *
105 * @iclass
106 */
108
110
111 ibqp->bcounter = 0;
112 ibqp->brdptr = ibqp->buffers;
113 ibqp->bwrptr = ibqp->buffers;
114 ibqp->ptr = NULL;
115 ibqp->top = NULL;
117}
118
119/**
120 * @brief Gets the next empty buffer from the queue.
121 * @note The function always returns the same buffer if called repeatedly.
122 *
123 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
124 * @return A pointer to the next buffer to be filled.
125 * @retval NULL if the queue is full.
126 *
127 * @iclass
128 */
130
132
133 if (ibqIsFullI(ibqp)) {
134 return NULL;
135 }
136
137 return ibqp->bwrptr + sizeof (size_t);
138}
139
140/**
141 * @brief Posts a new filled buffer to the queue.
142 *
143 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
144 * @param[in] size used size of the buffer, cannot be zero
145 *
146 * @iclass
147 */
149
151
152 osalDbgCheck((size > 0U) && (size <= (ibqp->bsize - sizeof (size_t))));
153 osalDbgAssert(!ibqIsFullI(ibqp), "buffers queue full");
154
155 /* Writing size field in the buffer.*/
156 *((size_t *)(void *)ibqp->bwrptr) = size;
157
158 /* Posting the buffer in the queue.*/
159 ibqp->bcounter++;
160 ibqp->bwrptr += ibqp->bsize;
161 if (ibqp->bwrptr >= ibqp->btop) {
162 ibqp->bwrptr = ibqp->buffers;
163 }
164
165 /* Waking up one waiting thread, if any.*/
167}
168
169/**
170 * @brief Gets the next filled buffer from the queue.
171 * @note The function always acquires the same buffer if called repeatedly.
172 * @post After calling the function the fields @p ptr and @p top are set
173 * at beginning and end of the buffer data or @p NULL if the queue
174 * is empty.
175 *
176 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
177 * @param[in] timeout the number of ticks before the operation timeouts,
178 * the following special values are allowed:
179 * - @a TIME_IMMEDIATE immediate timeout.
180 * - @a TIME_INFINITE no timeout.
181 * @return The operation status.
182 * @retval MSG_OK if a buffer has been acquired.
183 * @retval MSG_TIMEOUT if the specified time expired.
184 * @retval MSG_RESET if the queue has been reset or has been put in
185 * suspended state.
186 *
187 * @api
188 */
190 sysinterval_t timeout) {
191 msg_t msg;
192
193 osalSysLock();
194 msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
196
197 return msg;
198}
199
200 /**
201 * @brief Gets the next filled buffer from the queue.
202 * @note The function always acquires the same buffer if called repeatedly.
203 * @post After calling the function the fields @p ptr and @p top are set
204 * at beginning and end of the buffer data or @p NULL if the queue
205 * is empty.
206 *
207 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
208 * @param[in] timeout the number of ticks before the operation timeouts,
209 * the following special values are allowed:
210 * - @a TIME_IMMEDIATE immediate timeout.
211 * - @a TIME_INFINITE no timeout.
212 * @return The operation status.
213 * @retval MSG_OK if a buffer has been acquired.
214 * @retval MSG_TIMEOUT if the specified time expired.
215 * @retval MSG_RESET if the queue has been reset or has been put in
216 * suspended state.
217 *
218 * @sclass
219 */
221 sysinterval_t timeout) {
222
224
225 while (ibqIsEmptyI(ibqp)) {
226 if (ibqp->suspended) {
227 return MSG_RESET;
228 }
229 msg_t msg = osalThreadEnqueueTimeoutS(&ibqp->waiting, timeout);
230 if (msg < MSG_OK) {
231 return msg;
232 }
233 }
234
235 osalDbgAssert(!ibqIsEmptyI(ibqp), "still empty");
236
237 /* Setting up the "current" buffer and its boundary.*/
238 ibqp->ptr = ibqp->brdptr + sizeof (size_t);
239 ibqp->top = ibqp->ptr + *((size_t *)(void *)ibqp->brdptr);
240
241 return MSG_OK;
242}
243
244/**
245 * @brief Releases the buffer back in the queue.
246 * @note The object callback is called after releasing the buffer.
247 *
248 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
249 *
250 * @api
251 */
258
259 /**
260 * @brief Releases the buffer back in the queue.
261 * @note The object callback is called after releasing the buffer.
262 *
263 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
264 *
265 * @sclass
266 */
268
270 osalDbgAssert(!ibqIsEmptyI(ibqp), "buffers queue empty");
271
272 /* Freeing a buffer slot in the queue.*/
273 ibqp->bcounter--;
274 ibqp->brdptr += ibqp->bsize;
275 if (ibqp->brdptr >= ibqp->btop) {
276 ibqp->brdptr = ibqp->buffers;
277 }
278
279 /* No "current" buffer.*/
280 ibqp->ptr = NULL;
281
282 /* Notifying the buffer release.*/
283 if (ibqp->notify != NULL) {
284 ibqp->notify(ibqp);
285 }
286}
287
288/**
289 * @brief Input queue read with timeout.
290 * @details This function reads a byte value from an input queue. If
291 * the queue is empty then the calling thread is suspended until a
292 * new buffer arrives in the queue or a timeout occurs.
293 *
294 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
295 * @param[in] timeout the number of ticks before the operation timeouts,
296 * the following special values are allowed:
297 * - @a TIME_IMMEDIATE immediate timeout.
298 * - @a TIME_INFINITE no timeout.
299 * @return A byte value from the queue.
300 * @retval MSG_TIMEOUT if the specified time expired.
301 * @retval MSG_RESET if the queue has been reset or has been put in
302 * suspended state.
303 *
304 * @api
305 */
307 msg_t msg;
308
309 osalSysLock();
310
311 /* This condition indicates that a new buffer must be acquired.*/
312 if (ibqp->ptr == NULL) {
313 msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
314 if (msg != MSG_OK) {
316 return msg;
317 }
318 }
319
320 /* Next byte from the buffer.*/
321 msg = (msg_t)*ibqp->ptr;
322 ibqp->ptr++;
323
324 /* If the current buffer has been fully read then it is returned as
325 empty in the queue.*/
326 if (ibqp->ptr >= ibqp->top) {
328 }
329
331 return msg;
332}
333
334/**
335 * @brief Input queue read with timeout.
336 * @details The function reads data from an input queue into a buffer.
337 * The operation completes when the specified amount of data has been
338 * transferred or after the specified timeout or if the queue has
339 * been reset.
340 *
341 * @param[in] ibqp pointer to the @p input_buffers_queue_t object
342 * @param[out] bp pointer to the data buffer
343 * @param[in] n the maximum amount of data to be transferred, the
344 * value 0 is reserved
345 * @param[in] timeout the number of ticks before the operation timeouts,
346 * the following special values are allowed:
347 * - @a TIME_IMMEDIATE immediate timeout.
348 * - @a TIME_INFINITE no timeout.
349 * @return The number of bytes effectively transferred.
350 * @retval 0 if a timeout occurred.
351 *
352 * @api
353 */
354size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp,
355 size_t n, sysinterval_t timeout) {
356 size_t r = 0;
357
358 osalDbgCheck(n > 0U);
359
360 osalSysLock();
361
362 while (true) {
363 size_t size;
364
365 /* This condition indicates that a new buffer must be acquired.*/
366 if (ibqp->ptr == NULL) {
367 msg_t msg;
368
369 /* Getting a data buffer using the specified timeout.*/
370 msg = ibqGetFullBufferTimeoutS(ibqp, timeout);
371
372 /* Anything except MSG_OK interrupts the operation.*/
373 if (msg != MSG_OK) {
375 return r;
376 }
377 }
378
379 /* Size of the data chunk present in the current buffer.*/
380 size = (size_t)ibqp->top - (size_t)ibqp->ptr;
381 if (size > (n - r)) {
382 size = n - r;
383 }
384
385 /* Smaller chunks in order to not make the critical zone too long,
386 this impacts throughput however.*/
387 if (size > (size_t)BUFFERS_CHUNKS_SIZE) {
388 /* Giving the compiler a chance to optimize for a fixed size move.*/
389 memcpy(bp, ibqp->ptr, BUFFERS_CHUNKS_SIZE);
390 bp += (size_t)BUFFERS_CHUNKS_SIZE;
391 ibqp->ptr += (size_t)BUFFERS_CHUNKS_SIZE;
392 r += (size_t)BUFFERS_CHUNKS_SIZE;
393 }
394 else {
395 memcpy(bp, ibqp->ptr, size);
396 bp += size;
397 ibqp->ptr += size;
398 r += size;
399 }
400
401 /* Has the current data buffer been finished? if so then release it.*/
402 if (ibqp->ptr >= ibqp->top) {
404 }
405
406 /* Giving a preemption chance.*/
408 if (r >= n) {
409 return r;
410 }
411 osalSysLock();
412 }
413}
414
415/**
416 * @brief Initializes an output buffers queue object.
417 *
418 * @param[out] obqp pointer to the @p output_buffers_queue_t object
419 * @param[in] suspended initial state of the queue
420 * @param[in] bp pointer to a memory area allocated for buffers
421 * @param[in] size buffers size
422 * @param[in] n number of buffers
423 * @param[in] onfy callback called when a buffer is posted in the queue
424 * @param[in] link application defined pointer
425 *
426 * @init
427 */
428void obqObjectInit(output_buffers_queue_t *obqp, bool suspended, uint8_t *bp,
429 size_t size, size_t n, bqnotify_t onfy, void *link) {
430
431 osalDbgCheck((obqp != NULL) && (bp != NULL) && (size >= 2U));
432
434 obqp->suspended = suspended;
435 obqp->bcounter = n;
436 obqp->brdptr = bp;
437 obqp->bwrptr = bp;
438 obqp->btop = bp + ((size + sizeof (size_t)) * n);
439 obqp->bsize = size + sizeof (size_t);
440 obqp->bn = n;
441 obqp->buffers = bp;
442 obqp->ptr = NULL;
443 obqp->top = NULL;
444 obqp->notify = onfy;
445 obqp->link = link;
446}
447
448/**
449 * @brief Resets an output buffers queue.
450 * @details All the data in the output buffers queue is erased and lost, any
451 * waiting thread is resumed with status @p MSG_RESET.
452 * @note A reset operation can be used by a low level driver in order to
453 * obtain immediate attention from the high level layers.
454 *
455 * @param[in] obqp pointer to the @p output_buffers_queue_t object
456 *
457 * @iclass
458 */
460
462
463 obqp->bcounter = bqSizeX(obqp);
464 obqp->brdptr = obqp->buffers;
465 obqp->bwrptr = obqp->buffers;
466 obqp->ptr = NULL;
467 obqp->top = NULL;
469}
470
471/**
472 * @brief Gets the next filled buffer from the queue.
473 * @note The function always returns the same buffer if called repeatedly.
474 *
475 * @param[in] obqp pointer to the @p output_buffers_queue_t object
476 * @param[out] sizep pointer to the filled buffer size
477 * @return A pointer to the filled buffer.
478 * @retval NULL if the queue is empty.
479 *
480 * @iclass
481 */
483 size_t *sizep) {
484
486
487 if (obqIsEmptyI(obqp)) {
488 *sizep = 0U;
489 return NULL;
490 }
491
492 /* Buffer size.*/
493 *sizep = *((size_t *)(void *)obqp->brdptr);
494
495 return obqp->brdptr + sizeof (size_t);
496}
497
498/**
499 * @brief Releases the next filled buffer back in the queue.
500 *
501 * @param[in] obqp pointer to the @p output_buffers_queue_t object
502 *
503 * @iclass
504 */
506
508 osalDbgAssert(!obqIsEmptyI(obqp), "buffers queue empty");
509
510 /* Freeing a buffer slot in the queue.*/
511 obqp->bcounter++;
512 obqp->brdptr += obqp->bsize;
513 if (obqp->brdptr >= obqp->btop) {
514 obqp->brdptr = obqp->buffers;
515 }
516
517 /* Waking up one waiting thread, if any.*/
519}
520
521/**
522 * @brief Gets the next empty buffer from the queue.
523 * @note The function always acquires the same buffer if called repeatedly.
524 * @post After calling the function the fields @p ptr and @p top are set
525 * at beginning and end of the buffer data or @p NULL if the queue
526 * is empty.
527 *
528 * @param[in] obqp pointer to the @p output_buffers_queue_t object
529 * @param[in] timeout the number of ticks before the operation timeouts,
530 * the following special values are allowed:
531 * - @a TIME_IMMEDIATE immediate timeout.
532 * - @a TIME_INFINITE no timeout.
533 * @return The operation status.
534 * @retval MSG_OK if a buffer has been acquired.
535 * @retval MSG_TIMEOUT if the specified time expired.
536 * @retval MSG_RESET if the queue has been reset or has been put in
537 * suspended state.
538 *
539 * @api
540 */
542 sysinterval_t timeout) {
543 msg_t msg;
544
545 osalSysLock();
546 msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
548
549 return msg;
550}
551
552/**
553 * @brief Gets the next empty buffer from the queue.
554 * @note The function always acquires the same buffer if called repeatedly.
555 * @post After calling the function the fields @p ptr and @p top are set
556 * at beginning and end of the buffer data or @p NULL if the queue
557 * is empty.
558 *
559 * @param[in] obqp pointer to the @p output_buffers_queue_t object
560 * @param[in] timeout the number of ticks before the operation timeouts,
561 * the following special values are allowed:
562 * - @a TIME_IMMEDIATE immediate timeout.
563 * - @a TIME_INFINITE no timeout.
564 * @return The operation status.
565 * @retval MSG_OK if a buffer has been acquired.
566 * @retval MSG_TIMEOUT if the specified time expired.
567 * @retval MSG_RESET if the queue has been reset or has been put in
568 * suspended state.
569 *
570 * @sclass
571 */
573 sysinterval_t timeout) {
574
576
577 while (obqIsFullI(obqp)) {
578 if (obqp->suspended) {
579 return MSG_RESET;
580 }
581 msg_t msg = osalThreadEnqueueTimeoutS(&obqp->waiting, timeout);
582 if (msg < MSG_OK) {
583 return msg;
584 }
585 }
586
587 osalDbgAssert(!obqIsFullI(obqp), "still full");
588
589 /* Setting up the "current" buffer and its boundary.*/
590 obqp->ptr = obqp->bwrptr + sizeof (size_t);
591 obqp->top = obqp->bwrptr + obqp->bsize;
592
593 return MSG_OK;
594}
595
596/**
597 * @brief Posts a new filled buffer to the queue.
598 * @note The object callback is called after releasing the buffer.
599 *
600 * @param[in] obqp pointer to the @p output_buffers_queue_t object
601 * @param[in] size used size of the buffer, cannot be zero
602 *
603 * @api
604 */
606
607 osalSysLock();
608 obqPostFullBufferS(obqp, size);
610}
611
612/**
613 * @brief Posts a new filled buffer to the queue.
614 * @note The object callback is called after releasing the buffer.
615 *
616 * @param[in] obqp pointer to the @p output_buffers_queue_t object
617 * @param[in] size used size of the buffer, cannot be zero
618 *
619 * @sclass
620 */
622
624 osalDbgCheck((size > 0U) && (size <= (obqp->bsize - sizeof (size_t))));
625 osalDbgAssert(!obqIsFullI(obqp), "buffers queue full");
626
627 /* Writing size field in the buffer.*/
628 *((size_t *)(void *)obqp->bwrptr) = size;
629
630 /* Posting the buffer in the queue.*/
631 obqp->bcounter--;
632 obqp->bwrptr += obqp->bsize;
633 if (obqp->bwrptr >= obqp->btop) {
634 obqp->bwrptr = obqp->buffers;
635 }
636
637 /* No "current" buffer.*/
638 obqp->ptr = NULL;
639
640 /* Notifying the buffer release.*/
641 if (obqp->notify != NULL) {
642 obqp->notify(obqp);
643 }
644}
645
646/**
647 * @brief Output queue write with timeout.
648 * @details This function writes a byte value to an output queue. If
649 * the queue is full then the calling thread is suspended until a
650 * new buffer is freed in the queue or a timeout occurs.
651 *
652 * @param[in] obqp pointer to the @p output_buffers_queue_t object
653 * @param[in] b byte value to be transferred
654 * @param[in] timeout the number of ticks before the operation timeouts,
655 * the following special values are allowed:
656 * - @a TIME_IMMEDIATE immediate timeout.
657 * - @a TIME_INFINITE no timeout.
658 * @return A byte value from the queue.
659 * @retval MSG_TIMEOUT if the specified time expired.
660 * @retval MSG_RESET if the queue has been reset or has been put in
661 * suspended state.
662 *
663 * @api
664 */
666 sysinterval_t timeout) {
667 msg_t msg;
668
669 osalSysLock();
670
671 /* This condition indicates that a new buffer must be acquired.*/
672 if (obqp->ptr == NULL) {
673 msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
674 if (msg != MSG_OK) {
676 return msg;
677 }
678 }
679
680 /* Writing the byte to the buffer.*/
681 *obqp->ptr = b;
682 obqp->ptr++;
683
684 /* If the current buffer has been fully written then it is posted as
685 full in the queue.*/
686 if (obqp->ptr >= obqp->top) {
687 obqPostFullBufferS(obqp, obqp->bsize - sizeof (size_t));
688 }
689
691 return MSG_OK;
692}
693
694/**
695 * @brief Output queue write with timeout.
696 * @details The function writes data from a buffer to an output queue. The
697 * operation completes when the specified amount of data has been
698 * transferred or after the specified timeout or if the queue has
699 * been reset.
700 *
701 * @param[in] obqp pointer to the @p output_buffers_queue_t object
702 * @param[in] bp pointer to the data buffer
703 * @param[in] n the maximum amount of data to be transferred, the
704 * value 0 is reserved
705 * @param[in] timeout the number of ticks before the operation timeouts,
706 * the following special values are allowed:
707 * - @a TIME_IMMEDIATE immediate timeout.
708 * - @a TIME_INFINITE no timeout.
709 * @return The number of bytes effectively transferred.
710 * @retval 0 if a timeout occurred.
711 *
712 * @api
713 */
714size_t obqWriteTimeout(output_buffers_queue_t *obqp, const uint8_t *bp,
715 size_t n, sysinterval_t timeout) {
716 size_t w = 0;
717
718 osalDbgCheck(n > 0U);
719
720 osalSysLock();
721
722 while (true) {
723 size_t size;
724
725 /* This condition indicates that a new buffer must be acquired.*/
726 if (obqp->ptr == NULL) {
727 msg_t msg;
728
729 /* Getting an empty buffer using the specified timeout.*/
730 msg = obqGetEmptyBufferTimeoutS(obqp, timeout);
731
732 /* Anything except MSG_OK interrupts the operation.*/
733 if (msg != MSG_OK) {
735 return w;
736 }
737 }
738
739 /* Size of the space available in the current buffer.*/
740 size = (size_t)obqp->top - (size_t)obqp->ptr;
741 if (size > (n - w)) {
742 size = n - w;
743 }
744
745 /* Smaller chunks in order to not make the critical zone too long,
746 this impacts throughput however.*/
747 if (size > (size_t)BUFFERS_CHUNKS_SIZE) {
748 /* Giving the compiler a chance to optimize for a fixed size move.*/
749 memcpy(obqp->ptr, bp, (size_t)BUFFERS_CHUNKS_SIZE);
750 bp += (size_t)BUFFERS_CHUNKS_SIZE;
751 obqp->ptr += (size_t)BUFFERS_CHUNKS_SIZE;
752 w += (size_t)BUFFERS_CHUNKS_SIZE;
753 }
754 else {
755 memcpy(obqp->ptr, bp, size);
756 bp += size;
757 obqp->ptr += size;
758 w += size;
759 }
760
761 /* Has the current data buffer been finished? if so then release it.*/
762 if (obqp->ptr >= obqp->top) {
763 obqPostFullBufferS(obqp, obqp->bsize - sizeof (size_t));
764 }
765
766 /* Giving a preemption chance.*/
768 if (w >= n) {
769 return w;
770 }
771 osalSysLock();
772 }
773}
774
775/**
776 * @brief Flushes the current, partially filled, buffer to the queue.
777 * @note The notification callback is not invoked because the function
778 * is meant to be called from ISR context. An operation status is
779 * returned instead.
780 *
781 * @param[in] obqp pointer to the @p output_buffers_queue_t object
782 * @return The operation status.
783 * @retval false if no new filled buffer has been posted to the queue.
784 * @retval true if a new filled buffer has been posted to the queue.
785 *
786 * @iclass
787 */
789
791
792 /* If queue is empty and there is a buffer partially filled and
793 it is not being written.*/
794 if (obqIsEmptyI(obqp) && (obqp->ptr != NULL)) {
795 size_t size = (size_t)obqp->ptr - ((size_t)obqp->bwrptr + sizeof (size_t));
796
797 if (size > 0U) {
798
799 /* Writing size field in the buffer.*/
800 *((size_t *)(void *)obqp->bwrptr) = size;
801
802 /* Posting the buffer in the queue.*/
803 obqp->bcounter--;
804 obqp->bwrptr += obqp->bsize;
805 if (obqp->bwrptr >= obqp->btop) {
806 obqp->bwrptr = obqp->buffers;
807 }
808
809 /* No "current" buffer.*/
810 obqp->ptr = NULL;
811
812 return true;
813 }
814 }
815 return false;
816}
817
818/**
819 * @brief Flushes the current, partially filled, buffer to the queue.
820 *
821 * @param[in] obqp pointer to the @p output_buffers_queue_t object
822 *
823 * @api
824 */
826
827 osalSysLock();
828
829 /* If there is a buffer partially filled and not being written.*/
830 if (obqp->ptr != NULL) {
831 size_t size = ((size_t)obqp->ptr - (size_t)obqp->bwrptr) - sizeof (size_t);
832
833 if (size > 0U) {
834 obqPostFullBufferS(obqp, size);
835 }
836 }
837
839}
840/** @} */
uint8_t * ibqGetEmptyBufferI(input_buffers_queue_t *ibqp)
Gets the next empty buffer from the queue.
io_buffers_queue_t input_buffers_queue_t
Type of an input buffers queue.
void obqPostFullBuffer(output_buffers_queue_t *obqp, size_t size)
Posts a new filled buffer to the queue.
void obqFlush(output_buffers_queue_t *obqp)
Flushes the current, partially filled, buffer to the queue.
void ibqPostFullBufferI(input_buffers_queue_t *ibqp, size_t size)
Posts a new filled buffer to the queue.
#define ibqIsFullI(ibqp)
Evaluates to true if the specified input buffers queue is full.
uint8_t * obqGetFullBufferI(output_buffers_queue_t *obqp, size_t *sizep)
Gets the next filled buffer from the queue.
io_buffers_queue_t output_buffers_queue_t
Type of an output buffers queue.
bool obqTryFlushI(output_buffers_queue_t *obqp)
Flushes the current, partially filled, buffer to the queue.
msg_t ibqGetFullBufferTimeout(input_buffers_queue_t *ibqp, sysinterval_t timeout)
Gets the next filled buffer from the queue.
msg_t obqGetEmptyBufferTimeoutS(output_buffers_queue_t *obqp, sysinterval_t timeout)
Gets the next empty buffer from the queue.
void obqObjectInit(output_buffers_queue_t *obqp, bool suspended, uint8_t *bp, size_t size, size_t n, bqnotify_t onfy, void *link)
Initializes an output buffers queue object.
#define ibqIsEmptyI(ibqp)
Evaluates to true if the specified input buffers queue is empty.
size_t obqWriteTimeout(output_buffers_queue_t *obqp, const uint8_t *bp, size_t n, sysinterval_t timeout)
Output queue write with timeout.
void obqReleaseEmptyBufferI(output_buffers_queue_t *obqp)
Releases the next filled buffer back in the queue.
void obqPostFullBufferS(output_buffers_queue_t *obqp, size_t size)
Posts a new filled buffer to the queue.
void(* bqnotify_t)(io_buffers_queue_t *bqp)
Double buffer notification callback type.
Definition hal_buffers.h:70
void ibqObjectInit(input_buffers_queue_t *ibqp, bool suspended, uint8_t *bp, size_t size, size_t n, bqnotify_t infy, void *link)
Initializes an input buffers queue object.
Definition hal_buffers.c:76
void ibqReleaseEmptyBufferS(input_buffers_queue_t *ibqp)
Releases the buffer back in the queue.
msg_t ibqGetTimeout(input_buffers_queue_t *ibqp, sysinterval_t timeout)
Input queue read with timeout.
size_t ibqReadTimeout(input_buffers_queue_t *ibqp, uint8_t *bp, size_t n, sysinterval_t timeout)
Input queue read with timeout.
#define obqIsEmptyI(obqp)
Evaluates to true if the specified output buffers queue is empty.
msg_t ibqGetFullBufferTimeoutS(input_buffers_queue_t *ibqp, sysinterval_t timeout)
Gets the next filled buffer from the queue.
#define bqSizeX(bqp)
Returns the queue's number of buffers.
void ibqResetI(input_buffers_queue_t *ibqp)
Resets an input buffers queue.
#define obqIsFullI(obqp)
Evaluates to true if the specified output buffers queue is full.
msg_t obqGetEmptyBufferTimeout(output_buffers_queue_t *obqp, sysinterval_t timeout)
Gets the next empty buffer from the queue.
void obqResetI(output_buffers_queue_t *obqp)
Resets an output buffers queue.
void ibqReleaseEmptyBuffer(input_buffers_queue_t *ibqp)
Releases the buffer back in the queue.
#define BUFFERS_CHUNKS_SIZE
Maximum size of blocks copied in critical sections.
Definition hal_buffers.h:43
msg_t obqPutTimeout(output_buffers_queue_t *obqp, uint8_t b, sysinterval_t timeout)
Output queue write with timeout.
msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout)
Enqueues the caller thread.
Definition osal.c:273
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition osal.h:601
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition osal.h:611
void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up all threads from the queue.
Definition osal.c:305
static void osalThreadQueueObjectInit(threads_queue_t *tqp)
Initializes a threads queue object.
Definition osal.h:725
int32_t msg_t
Type of a message.
Definition osal.h:159
uint32_t sysinterval_t
Type of system time interval.
Definition osal.h:169
#define MSG_OK
Definition osal.h:56
#define osalDbgCheckClassS()
S-Class state check.
Definition osal.h:304
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
#define MSG_RESET
Definition osal.h:58
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg)
Dequeues and wakes up one thread from the queue, if any.
Definition osal.c:290
#define osalDbgCheckClassI()
I-Class state check.
Definition osal.h:298
HAL subsystem header.
uint8_t * brdptr
Buffer read pointer.
Definition hal_buffers.h:95
bqnotify_t notify
Data notification callback.
size_t bn
Number of buffers.
uint8_t * buffers
Queue of buffer objects.
uint8_t * btop
Pointer to the buffers boundary.
Definition hal_buffers.h:99
bool suspended
Queue suspended state flag.
Definition hal_buffers.h:83
size_t bsize
Size of buffers.
void * link
Application defined field.
uint8_t * bwrptr
Buffer write pointer.
Definition hal_buffers.h:91
volatile size_t bcounter
Active buffers counter.
Definition hal_buffers.h:87
threads_queue_t waiting
Queue of waiting threads.
Definition hal_buffers.h:79
uint8_t * top
Boundary for R/W sequential access.
uint8_t * ptr
Pointer for R/W sequential access.