update

Committer:
kwengryn3
Date:
Thu Apr 08 16:43:07 2021 +0000
Revision:
0:bfff72fb3650
update;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kwengryn3 0:bfff72fb3650 1 /* mbed Microcontroller Library
kwengryn3 0:bfff72fb3650 2 * Copyright (c) 2015 ARM Limited
kwengryn3 0:bfff72fb3650 3 * SPDX-License-Identifier: Apache-2.0
kwengryn3 0:bfff72fb3650 4 *
kwengryn3 0:bfff72fb3650 5 * Licensed under the Apache License, Version 2.0 (the "License");
kwengryn3 0:bfff72fb3650 6 * you may not use this file except in compliance with the License.
kwengryn3 0:bfff72fb3650 7 * You may obtain a copy of the License at
kwengryn3 0:bfff72fb3650 8 *
kwengryn3 0:bfff72fb3650 9 * http://www.apache.org/licenses/LICENSE-2.0
kwengryn3 0:bfff72fb3650 10 *
kwengryn3 0:bfff72fb3650 11 * Unless required by applicable law or agreed to in writing, software
kwengryn3 0:bfff72fb3650 12 * distributed under the License is distributed on an "AS IS" BASIS,
kwengryn3 0:bfff72fb3650 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kwengryn3 0:bfff72fb3650 14 * See the License for the specific language governing permissions and
kwengryn3 0:bfff72fb3650 15 * limitations under the License.
kwengryn3 0:bfff72fb3650 16 */
kwengryn3 0:bfff72fb3650 17 #ifndef MBED_CIRCULARBUFFER_H
kwengryn3 0:bfff72fb3650 18 #define MBED_CIRCULARBUFFER_H
kwengryn3 0:bfff72fb3650 19
kwengryn3 0:bfff72fb3650 20 #include "platform/mbed_critical.h"
kwengryn3 0:bfff72fb3650 21 #include "platform/mbed_assert.h"
kwengryn3 0:bfff72fb3650 22
kwengryn3 0:bfff72fb3650 23 namespace mbed {
kwengryn3 0:bfff72fb3650 24
kwengryn3 0:bfff72fb3650 25 namespace internal {
kwengryn3 0:bfff72fb3650 26 /* Detect if CounterType of the Circular buffer is of unsigned type. */
kwengryn3 0:bfff72fb3650 27 template<typename T>
kwengryn3 0:bfff72fb3650 28 struct is_unsigned {
kwengryn3 0:bfff72fb3650 29 static const bool value = false;
kwengryn3 0:bfff72fb3650 30 };
kwengryn3 0:bfff72fb3650 31 template<>
kwengryn3 0:bfff72fb3650 32 struct is_unsigned<unsigned char> {
kwengryn3 0:bfff72fb3650 33 static const bool value = true;
kwengryn3 0:bfff72fb3650 34 };
kwengryn3 0:bfff72fb3650 35 template<>
kwengryn3 0:bfff72fb3650 36 struct is_unsigned<unsigned short> {
kwengryn3 0:bfff72fb3650 37 static const bool value = true;
kwengryn3 0:bfff72fb3650 38 };
kwengryn3 0:bfff72fb3650 39 template<>
kwengryn3 0:bfff72fb3650 40 struct is_unsigned<unsigned int> {
kwengryn3 0:bfff72fb3650 41 static const bool value = true;
kwengryn3 0:bfff72fb3650 42 };
kwengryn3 0:bfff72fb3650 43 template<>
kwengryn3 0:bfff72fb3650 44 struct is_unsigned<unsigned long> {
kwengryn3 0:bfff72fb3650 45 static const bool value = true;
kwengryn3 0:bfff72fb3650 46 };
kwengryn3 0:bfff72fb3650 47 template<>
kwengryn3 0:bfff72fb3650 48 struct is_unsigned<unsigned long long> {
kwengryn3 0:bfff72fb3650 49 static const bool value = true;
kwengryn3 0:bfff72fb3650 50 };
kwengryn3 0:bfff72fb3650 51 };
kwengryn3 0:bfff72fb3650 52
kwengryn3 0:bfff72fb3650 53 /** \addtogroup platform */
kwengryn3 0:bfff72fb3650 54 /** @{*/
kwengryn3 0:bfff72fb3650 55 /**
kwengryn3 0:bfff72fb3650 56 * \defgroup platform_CircularBuffer CircularBuffer functions
kwengryn3 0:bfff72fb3650 57 * @{
kwengryn3 0:bfff72fb3650 58 */
kwengryn3 0:bfff72fb3650 59
kwengryn3 0:bfff72fb3650 60 /** Templated Circular buffer class
kwengryn3 0:bfff72fb3650 61 *
kwengryn3 0:bfff72fb3650 62 * @note Synchronization level: Interrupt safe
kwengryn3 0:bfff72fb3650 63 * @note CounterType must be unsigned and consistent with BufferSize
kwengryn3 0:bfff72fb3650 64 */
kwengryn3 0:bfff72fb3650 65 template<typename T, uint32_t BufferSize, typename CounterType = uint32_t>
kwengryn3 0:bfff72fb3650 66 class CircularBuffer {
kwengryn3 0:bfff72fb3650 67 public:
kwengryn3 0:bfff72fb3650 68 CircularBuffer() : _head(0), _tail(0), _full(false)
kwengryn3 0:bfff72fb3650 69 {
kwengryn3 0:bfff72fb3650 70 MBED_STATIC_ASSERT(
kwengryn3 0:bfff72fb3650 71 internal::is_unsigned<CounterType>::value,
kwengryn3 0:bfff72fb3650 72 "CounterType must be unsigned"
kwengryn3 0:bfff72fb3650 73 );
kwengryn3 0:bfff72fb3650 74
kwengryn3 0:bfff72fb3650 75 MBED_STATIC_ASSERT(
kwengryn3 0:bfff72fb3650 76 (sizeof(CounterType) >= sizeof(uint32_t)) ||
kwengryn3 0:bfff72fb3650 77 (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))),
kwengryn3 0:bfff72fb3650 78 "Invalid BufferSize for the CounterType"
kwengryn3 0:bfff72fb3650 79 );
kwengryn3 0:bfff72fb3650 80 }
kwengryn3 0:bfff72fb3650 81
kwengryn3 0:bfff72fb3650 82 ~CircularBuffer()
kwengryn3 0:bfff72fb3650 83 {
kwengryn3 0:bfff72fb3650 84 }
kwengryn3 0:bfff72fb3650 85
kwengryn3 0:bfff72fb3650 86 /** Push the transaction to the buffer. This overwrites the buffer if it's
kwengryn3 0:bfff72fb3650 87 * full
kwengryn3 0:bfff72fb3650 88 *
kwengryn3 0:bfff72fb3650 89 * @param data Data to be pushed to the buffer
kwengryn3 0:bfff72fb3650 90 */
kwengryn3 0:bfff72fb3650 91 void push(const T &data)
kwengryn3 0:bfff72fb3650 92 {
kwengryn3 0:bfff72fb3650 93 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 94 if (full()) {
kwengryn3 0:bfff72fb3650 95 _tail++;
kwengryn3 0:bfff72fb3650 96 if (_tail == BufferSize) {
kwengryn3 0:bfff72fb3650 97 _tail = 0;
kwengryn3 0:bfff72fb3650 98 }
kwengryn3 0:bfff72fb3650 99 }
kwengryn3 0:bfff72fb3650 100 _pool[_head++] = data;
kwengryn3 0:bfff72fb3650 101 if (_head == BufferSize) {
kwengryn3 0:bfff72fb3650 102 _head = 0;
kwengryn3 0:bfff72fb3650 103 }
kwengryn3 0:bfff72fb3650 104 if (_head == _tail) {
kwengryn3 0:bfff72fb3650 105 _full = true;
kwengryn3 0:bfff72fb3650 106 }
kwengryn3 0:bfff72fb3650 107 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 108 }
kwengryn3 0:bfff72fb3650 109
kwengryn3 0:bfff72fb3650 110 /** Pop the transaction from the buffer
kwengryn3 0:bfff72fb3650 111 *
kwengryn3 0:bfff72fb3650 112 * @param data Data to be popped from the buffer
kwengryn3 0:bfff72fb3650 113 * @return True if the buffer is not empty and data contains a transaction, false otherwise
kwengryn3 0:bfff72fb3650 114 */
kwengryn3 0:bfff72fb3650 115 bool pop(T &data)
kwengryn3 0:bfff72fb3650 116 {
kwengryn3 0:bfff72fb3650 117 bool data_popped = false;
kwengryn3 0:bfff72fb3650 118 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 119 if (!empty()) {
kwengryn3 0:bfff72fb3650 120 data = _pool[_tail++];
kwengryn3 0:bfff72fb3650 121 if (_tail == BufferSize) {
kwengryn3 0:bfff72fb3650 122 _tail = 0;
kwengryn3 0:bfff72fb3650 123 }
kwengryn3 0:bfff72fb3650 124 _full = false;
kwengryn3 0:bfff72fb3650 125 data_popped = true;
kwengryn3 0:bfff72fb3650 126 }
kwengryn3 0:bfff72fb3650 127 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 128 return data_popped;
kwengryn3 0:bfff72fb3650 129 }
kwengryn3 0:bfff72fb3650 130
kwengryn3 0:bfff72fb3650 131 /** Check if the buffer is empty
kwengryn3 0:bfff72fb3650 132 *
kwengryn3 0:bfff72fb3650 133 * @return True if the buffer is empty, false if not
kwengryn3 0:bfff72fb3650 134 */
kwengryn3 0:bfff72fb3650 135 bool empty() const
kwengryn3 0:bfff72fb3650 136 {
kwengryn3 0:bfff72fb3650 137 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 138 bool is_empty = (_head == _tail) && !_full;
kwengryn3 0:bfff72fb3650 139 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 140 return is_empty;
kwengryn3 0:bfff72fb3650 141 }
kwengryn3 0:bfff72fb3650 142
kwengryn3 0:bfff72fb3650 143 /** Check if the buffer is full
kwengryn3 0:bfff72fb3650 144 *
kwengryn3 0:bfff72fb3650 145 * @return True if the buffer is full, false if not
kwengryn3 0:bfff72fb3650 146 */
kwengryn3 0:bfff72fb3650 147 bool full() const
kwengryn3 0:bfff72fb3650 148 {
kwengryn3 0:bfff72fb3650 149 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 150 bool full = _full;
kwengryn3 0:bfff72fb3650 151 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 152 return full;
kwengryn3 0:bfff72fb3650 153 }
kwengryn3 0:bfff72fb3650 154
kwengryn3 0:bfff72fb3650 155 /** Reset the buffer
kwengryn3 0:bfff72fb3650 156 *
kwengryn3 0:bfff72fb3650 157 */
kwengryn3 0:bfff72fb3650 158 void reset()
kwengryn3 0:bfff72fb3650 159 {
kwengryn3 0:bfff72fb3650 160 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 161 _head = 0;
kwengryn3 0:bfff72fb3650 162 _tail = 0;
kwengryn3 0:bfff72fb3650 163 _full = false;
kwengryn3 0:bfff72fb3650 164 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 165 }
kwengryn3 0:bfff72fb3650 166
kwengryn3 0:bfff72fb3650 167 /** Get the number of elements currently stored in the circular_buffer */
kwengryn3 0:bfff72fb3650 168 CounterType size() const
kwengryn3 0:bfff72fb3650 169 {
kwengryn3 0:bfff72fb3650 170 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 171 CounterType elements;
kwengryn3 0:bfff72fb3650 172 if (!_full) {
kwengryn3 0:bfff72fb3650 173 if (_head < _tail) {
kwengryn3 0:bfff72fb3650 174 elements = BufferSize + _head - _tail;
kwengryn3 0:bfff72fb3650 175 } else {
kwengryn3 0:bfff72fb3650 176 elements = _head - _tail;
kwengryn3 0:bfff72fb3650 177 }
kwengryn3 0:bfff72fb3650 178 } else {
kwengryn3 0:bfff72fb3650 179 elements = BufferSize;
kwengryn3 0:bfff72fb3650 180 }
kwengryn3 0:bfff72fb3650 181 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 182 return elements;
kwengryn3 0:bfff72fb3650 183 }
kwengryn3 0:bfff72fb3650 184
kwengryn3 0:bfff72fb3650 185 /** Peek into circular buffer without popping
kwengryn3 0:bfff72fb3650 186 *
kwengryn3 0:bfff72fb3650 187 * @param data Data to be peeked from the buffer
kwengryn3 0:bfff72fb3650 188 * @return True if the buffer is not empty and data contains a transaction, false otherwise
kwengryn3 0:bfff72fb3650 189 */
kwengryn3 0:bfff72fb3650 190 bool peek(T &data) const
kwengryn3 0:bfff72fb3650 191 {
kwengryn3 0:bfff72fb3650 192 bool data_updated = false;
kwengryn3 0:bfff72fb3650 193 core_util_critical_section_enter();
kwengryn3 0:bfff72fb3650 194 if (!empty()) {
kwengryn3 0:bfff72fb3650 195 data = _pool[_tail];
kwengryn3 0:bfff72fb3650 196 data_updated = true;
kwengryn3 0:bfff72fb3650 197 }
kwengryn3 0:bfff72fb3650 198 core_util_critical_section_exit();
kwengryn3 0:bfff72fb3650 199 return data_updated;
kwengryn3 0:bfff72fb3650 200 }
kwengryn3 0:bfff72fb3650 201
kwengryn3 0:bfff72fb3650 202 private:
kwengryn3 0:bfff72fb3650 203 T _pool[BufferSize];
kwengryn3 0:bfff72fb3650 204 CounterType _head;
kwengryn3 0:bfff72fb3650 205 CounterType _tail;
kwengryn3 0:bfff72fb3650 206 bool _full;
kwengryn3 0:bfff72fb3650 207 };
kwengryn3 0:bfff72fb3650 208
kwengryn3 0:bfff72fb3650 209 /**@}*/
kwengryn3 0:bfff72fb3650 210
kwengryn3 0:bfff72fb3650 211 /**@}*/
kwengryn3 0:bfff72fb3650 212
kwengryn3 0:bfff72fb3650 213 }
kwengryn3 0:bfff72fb3650 214
kwengryn3 0:bfff72fb3650 215 #endif