From 8aa12bb43d1a6dd2da24f7ff20a2ca0f2e04177d Mon Sep 17 00:00:00 2001 From: Jaedeok Kim Date: Sun, 27 Aug 2023 23:48:51 +0900 Subject: [PATCH 01/20] Fix a small typo in README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6bce10d..42553d5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Library provides generic FIFO ring buffer implementation. * Uses optimized memory copy instead of loops to read/write data from/to memory * Thread safe when used as pipe with single write and single read entries - when CPU read/write operation for `size_t` are single instruction (ARM Cortex-M for instance) * Interrupt safe when used as pipe with single write and single read entries - when CPU read/write operation for `size_t` are single instruction (ARM Cortex-M for instance) -* For CPU systems with smaller achitecture than `sizeof(size_t)` (AVR for instance), atomic protection is required for read-write operation of buffer writes +* For CPU systems with smaller architecture than `sizeof(size_t)` (AVR for instance), atomic protection is required for read-write operation of buffer writes * Suitable for DMA transfers from and to memory with zero-copy overhead between buffer and application memory * Supports data peek, skip for read and advance for write * Implements support for event notifications @@ -21,7 +21,7 @@ Library provides generic FIFO ring buffer implementation. ## Contribute -Fresh contributions are always welcome. Simple instructions to proceed:: +Fresh contributions are always welcome. Simple instructions to proceed: 1. Fork Github repository 2. Follow [C style & coding rules](https://github.com/MaJerle/c-code-style) already used in the project @@ -30,4 +30,4 @@ Fresh contributions are always welcome. Simple instructions to proceed:: Alternatively you may: 1. Report a bug -2. Ask for a feature request \ No newline at end of file +2. Ask for a feature request From 4fc8976e74e06c598a08498c4bdd3ef6d8412fa3 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 28 Aug 2023 21:42:55 +0200 Subject: [PATCH 02/20] Add readthedocs YAML file --- .readthedocs.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..dd64b05 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,18 @@ +version: 2 +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Python configuration +python: + install: + - requirements: docs/requirements.txt + +formats: + - pdf + - epub From bbe008ed2c7c648664c190cd325f012e23c5bb62 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 16 Sep 2023 18:24:08 +0200 Subject: [PATCH 03/20] Update overwrite function docs --- lwrb/src/lwrb/lwrb_ex.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lwrb/src/lwrb/lwrb_ex.c b/lwrb/src/lwrb/lwrb_ex.c index aea8357..203eace 100644 --- a/lwrb/src/lwrb/lwrb_ex.c +++ b/lwrb/src/lwrb/lwrb_ex.c @@ -41,7 +41,9 @@ #endif /** - * \brief Similar to \ref lwrb_write, writes data to buffer, will overwrite existing values + * \brief Writes data to buffer with overwrite function, if no enough space to hold + * complete input data object. + * \note Similar to \ref lwrb_write but overwrites * \param[in] buff: Buffer handle * \param[in] data: Data to write to ring buffer * \param[in] btw: Bytes To Write, length @@ -62,10 +64,18 @@ lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw) { /* Process complete input array */ max_cap = buff->size - 1; /* Maximum capacity buffer can hold */ - if (btw > max_cap) { /* When buffer is larger than max buffer capacity */ - d += btw - max_cap; /* Advance data */ - btw = max_cap; /* Limit data to write */ - lwrb_reset(buff); /* Reset buffer */ + if (btw > max_cap) { + /* + * When data to write is larger than max buffer capacity, + * we can reset the buffer and simply write last part of + * the input buffer. + * + * This is done here, by calculating remaining + * length and then advancing to the end of input buffer + */ + d += btw - max_cap; /* Advance data */ + btw = max_cap; /* Limit data to write */ + lwrb_reset(buff); /* Reset buffer */ } else { /* * Bytes to write is less than capacity From 106437ee8e4667c4d250a319d2cf9c3178a83a55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 03:25:31 +0000 Subject: [PATCH 04/20] Bump urllib3 from 1.26.15 to 1.26.17 in /docs Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.15 to 1.26.17. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.15...1.26.17) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index bf1bde0..27e9780 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ sphinx>=3.5.1 breathe>=4.9.1 -urllib3==1.26.15 +urllib3==1.26.17 docutils==0.16 colorama sphinx_rtd_theme>=1.0.0 From b3c3ef6a577bc73bd215d5d070f9ecb284cfbabe Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sun, 15 Oct 2023 16:29:42 +0200 Subject: [PATCH 05/20] Fix wrong docs text --- docs/user-manual/thread-safety.rst | 4 ++-- third_party/Unity | 2 +- third_party/cmake-modules | 2 +- third_party/sanitizers-cmake | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/user-manual/thread-safety.rst b/docs/user-manual/thread-safety.rst index 61ad19b..62d24b7 100644 --- a/docs/user-manual/thread-safety.rst +++ b/docs/user-manual/thread-safety.rst @@ -31,8 +31,8 @@ Therefore multiple *conditional* checks are guaranteed to be performed on the sa .. note:: Even single entry and single exit points may introduce race condition, especially on smaller system, such as 8-bit or 16-bit system, or in general, - where arbitrary type (normaly `size_t`) is `sizeof(type) < architecture_size`. - This is solved by C11 atomic library, that ensures atomic reads and writes to key structure members + where arbitrary type (normaly `size_t`) is `sizeof(type) > architecture_size`. + This is solved by C11 atomic library, that ensures atomic reads and writes to key structure members. Thread safety gets completely broken when application does one of the following: diff --git a/third_party/Unity b/third_party/Unity index d826f09..5a36b19 160000 --- a/third_party/Unity +++ b/third_party/Unity @@ -1 +1 @@ -Subproject commit d826f09bbf140b0acb227066b34a8653ea4b8717 +Subproject commit 5a36b197fb34c0a77ac891c355596cb5c25aaf5b diff --git a/third_party/cmake-modules b/third_party/cmake-modules index 1b68d17..877bab9 160000 --- a/third_party/cmake-modules +++ b/third_party/cmake-modules @@ -1 +1 @@ -Subproject commit 1b68d17d3e3321c08092f994a40e0b6a13dff817 +Subproject commit 877bab9dd1b17468c5d939cacaa2ad7ba99d1977 diff --git a/third_party/sanitizers-cmake b/third_party/sanitizers-cmake index 99e159e..a6748f4 160000 --- a/third_party/sanitizers-cmake +++ b/third_party/sanitizers-cmake @@ -1 +1 @@ -Subproject commit 99e159ec9bc8dd362b08d18436bd40ff0648417b +Subproject commit a6748f4f51273d86312e3d27ebe5277c9b1ff870 From 9e898437ebbb9daa29bdb87b4b40a96e11ef0e2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 01:17:09 +0000 Subject: [PATCH 06/20] Bump urllib3 from 1.26.17 to 1.26.18 in /docs Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.17 to 1.26.18. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.17...1.26.18) --- updated-dependencies: - dependency-name: urllib3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 27e9780..d70b1a4 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ sphinx>=3.5.1 breathe>=4.9.1 -urllib3==1.26.17 +urllib3==1.26.18 docutils==0.16 colorama sphinx_rtd_theme>=1.0.0 From 1b7b19a7e6c667841d60dcd307e625bbb8527b1a Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 21 Oct 2023 10:44:56 +0200 Subject: [PATCH 07/20] Replace size_t with lwrb_sz_t type instead --- CHANGELOG.md | 5 ++++ dev/main.c | 8 +++--- lwrb/src/include/lwrb/lwrb.h | 45 +++++++++++++++++------------ lwrb/src/lwrb/lwrb.c | 56 ++++++++++++++++++------------------ lwrb/src/lwrb/lwrb_ex.c | 16 +++++------ 5 files changed, 71 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1666c0b..c52292a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Develop +- Preparation for `v3.1` +- Replace `size_t` with custom defined type `lwrb_sz_t` which matches atomicity requirements +- `lwrb_sz_t` is by default typedef-ed as `unsigned long` +- Prepare `lwrb_write_ex` and `lwrb_read_ex` function + ## v3.0.0 - Added macros for optional STDATOMIC. Global `-DLWRB_DISABLE_ATOMIC` macro will disable C11 `` functionality. diff --git a/dev/main.c b/dev/main.c index 330be0a..95a2f92 100644 --- a/dev/main.c +++ b/dev/main.c @@ -12,7 +12,7 @@ lwrb_t buff; uint8_t tmp[8]; void -my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, size_t len) { +my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, lwrb_sz_t len) { (void)buff; (void)len; switch (type) { @@ -25,7 +25,7 @@ my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, size_t len) { int main() { - size_t len; + lwrb_sz_t len; /* Init buffer */ lwrb_init(&buff, lwrb_data, sizeof(lwrb_data)); @@ -99,7 +99,7 @@ main() { { #define MOVE_TEST(_exp_content_, _exp_move_len_, _exp_buff_len_) \ do { \ - size_t move_len; \ + lwrb_sz_t move_len; \ move_len = lwrb_move(&dst, &src); \ len = lwrb_peek(&dst, 0, tmp, dst.size); \ printf("move data: len: %d, dest data: %.*s, as_expected: %u\r\n", (int)len, (int)len, tmp, \ @@ -137,7 +137,7 @@ main() { { #define FIND_TEST(_bts_, _bts_len_, _start_offset_, _exp_result_) \ do { \ - size_t found_idx; \ + lwrb_sz_t found_idx; \ uint8_t found; \ found = lwrb_find(&buff, (_bts_), (_bts_len_), (_start_offset_), &found_idx); \ printf("Find \"%s\" (len %d), start_offset: %d, found_index: %d; Found: %d; As expected: %d\r\n", (_bts_), \ diff --git a/lwrb/src/include/lwrb/lwrb.h b/lwrb/src/include/lwrb/lwrb.h index a8468bc..c67cb99 100644 --- a/lwrb/src/include/lwrb/lwrb.h +++ b/lwrb/src/include/lwrb/lwrb.h @@ -34,6 +34,7 @@ #ifndef LWRB_HDR_H #define LWRB_HDR_H +#include #include #include @@ -48,10 +49,12 @@ extern "C" { */ #ifdef LWRB_DISABLE_ATOMIC -typedef unsigned long lwrb_ulong_t; +typedef unsigned long lwrb_sz_atomic_t; +typedef unsigned long lwrb_sz_t; #else #include -typedef atomic_ulong lwrb_ulong_t; +typedef atomic_ulong lwrb_sz_atomic_t; +typedef unsigned long lwrb_sz_t; #endif /** @@ -74,48 +77,52 @@ struct lwrb; * \param[in] evt: Event type * \param[in] bp: Number of bytes written or read (when used), depends on event type */ -typedef void (*lwrb_evt_fn)(struct lwrb* buff, lwrb_evt_type_t evt, size_t bp); +typedef void (*lwrb_evt_fn)(struct lwrb* buff, lwrb_evt_type_t evt, lwrb_sz_t bp); /** * \brief Buffer structure */ typedef struct lwrb { uint8_t* buff; /*!< Pointer to buffer data. Buffer is considered initialized when `buff != NULL` and `size > 0` */ - size_t size; /*!< Size of buffer data. Size of actual buffer is `1` byte less than value holds */ - lwrb_ulong_t r; /*!< Next read pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */ - lwrb_ulong_t w; /*!< Next write pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */ + lwrb_sz_t size; /*!< Size of buffer data. Size of actual buffer is `1` byte less than value holds */ + lwrb_sz_atomic_t r; /*!< Next read pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */ + lwrb_sz_atomic_t w; /*!< Next write pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */ lwrb_evt_fn evt_fn; /*!< Pointer to event callback function */ } lwrb_t; -uint8_t lwrb_init(lwrb_t* buff, void* buffdata, size_t size); +uint8_t lwrb_init(lwrb_t* buff, void* buffdata, lwrb_sz_t size); uint8_t lwrb_is_ready(lwrb_t* buff); void lwrb_free(lwrb_t* buff); void lwrb_reset(lwrb_t* buff); void lwrb_set_evt_fn(lwrb_t* buff, lwrb_evt_fn fn); /* Read/Write functions */ -size_t lwrb_write(lwrb_t* buff, const void* data, size_t btw); -size_t lwrb_read(lwrb_t* buff, void* data, size_t btr); -size_t lwrb_peek(const lwrb_t* buff, size_t skip_count, void* data, size_t btp); +lwrb_sz_t lwrb_write(lwrb_t* buff, const void* data, lwrb_sz_t btw); +lwrb_sz_t lwrb_read(lwrb_t* buff, void* data, lwrb_sz_t btr); +lwrb_sz_t lwrb_peek(const lwrb_t* buff, lwrb_sz_t skip_count, void* data, lwrb_sz_t btp); + +/* Extended read/write functions */ +uint8_t lwrb_write_ex(lwrb_t* buff, const void* data, lwrb_sz_t btw, lwrb_sz_t* bw, uint16_t flags); +uint8_t lwrb_read_ex(lwrb_t* buff, void* data, lwrb_sz_t btr, lwrb_sz_t* br, uint16_t flags); /* Buffer size information */ -size_t lwrb_get_free(const lwrb_t* buff); -size_t lwrb_get_full(const lwrb_t* buff); +lwrb_sz_t lwrb_get_free(const lwrb_t* buff); +lwrb_sz_t lwrb_get_full(const lwrb_t* buff); /* Read data block management */ void* lwrb_get_linear_block_read_address(const lwrb_t* buff); -size_t lwrb_get_linear_block_read_length(const lwrb_t* buff); -size_t lwrb_skip(lwrb_t* buff, size_t len); +lwrb_sz_t lwrb_get_linear_block_read_length(const lwrb_t* buff); +lwrb_sz_t lwrb_skip(lwrb_t* buff, lwrb_sz_t len); /* Write data block management */ void* lwrb_get_linear_block_write_address(const lwrb_t* buff); -size_t lwrb_get_linear_block_write_length(const lwrb_t* buff); -size_t lwrb_advance(lwrb_t* buff, size_t len); +lwrb_sz_t lwrb_get_linear_block_write_length(const lwrb_t* buff); +lwrb_sz_t lwrb_advance(lwrb_t* buff, lwrb_sz_t len); /* Search in buffer */ -uint8_t lwrb_find(const lwrb_t* buff, const void* bts, size_t len, size_t start_offset, size_t* found_idx); -size_t lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw); -size_t lwrb_move(lwrb_t* dest, lwrb_t* src); +uint8_t lwrb_find(const lwrb_t* buff, const void* bts, lwrb_sz_t len, lwrb_sz_t start_offset, lwrb_sz_t* found_idx); +lwrb_sz_t lwrb_overwrite(lwrb_t* buff, const void* data, lwrb_sz_t btw); +lwrb_sz_t lwrb_move(lwrb_t* dest, lwrb_t* src); /** * \} diff --git a/lwrb/src/lwrb/lwrb.c b/lwrb/src/lwrb/lwrb.c index 3bb5dd0..aabbbe9 100644 --- a/lwrb/src/lwrb/lwrb.c +++ b/lwrb/src/lwrb/lwrb.c @@ -67,7 +67,7 @@ * \return `1` on success, `0` otherwise */ uint8_t -lwrb_init(lwrb_t* buff, void* buffdata, size_t size) { +lwrb_init(lwrb_t* buff, void* buffdata, lwrb_sz_t size) { if (buff == NULL || buffdata == NULL || size == 0) { return 0; } @@ -126,9 +126,9 @@ lwrb_set_evt_fn(lwrb_t* buff, lwrb_evt_fn evt_fn) { * When returned value is less than `btw`, there was no enough memory available * to copy full data array */ -size_t -lwrb_write(lwrb_t* buff, const void* data, size_t btw) { - size_t tocopy, free, buff_w_ptr; +lwrb_sz_t +lwrb_write(lwrb_t* buff, const void* data, lwrb_sz_t btw) { + lwrb_sz_t tocopy, free, buff_w_ptr; const uint8_t* d = data; if (!BUF_IS_VALID(buff) || data == NULL || btw == 0) { @@ -179,9 +179,9 @@ lwrb_write(lwrb_t* buff, const void* data, size_t btw) { * \param[in] btr: Number of bytes to read * \return Number of bytes read and copied to data array */ -size_t -lwrb_read(lwrb_t* buff, void* data, size_t btr) { - size_t tocopy, full, buff_r_ptr; +lwrb_sz_t +lwrb_read(lwrb_t* buff, void* data, lwrb_sz_t btr) { + lwrb_sz_t tocopy, full, buff_r_ptr; uint8_t* d = data; if (!BUF_IS_VALID(buff) || data == NULL || btr == 0) { @@ -231,9 +231,9 @@ lwrb_read(lwrb_t* buff, void* data, size_t btr) { * \param[in] btp: Number of bytes to peek * \return Number of bytes peeked and written to output array */ -size_t -lwrb_peek(const lwrb_t* buff, size_t skip_count, void* data, size_t btp) { - size_t full, tocopy, r; +lwrb_sz_t +lwrb_peek(const lwrb_t* buff, lwrb_sz_t skip_count, void* data, lwrb_sz_t btp) { + lwrb_sz_t full, tocopy, r; uint8_t* d = data; if (!BUF_IS_VALID(buff) || data == NULL || btp == 0) { @@ -278,9 +278,9 @@ lwrb_peek(const lwrb_t* buff, size_t skip_count, void* data, size_t btp) { * \param[in] buff: Buffer handle * \return Number of free bytes in memory */ -size_t +lwrb_sz_t lwrb_get_free(const lwrb_t* buff) { - size_t size, w, r; + lwrb_sz_t size, w, r; if (!BUF_IS_VALID(buff)) { return 0; @@ -324,9 +324,9 @@ lwrb_get_free(const lwrb_t* buff) { * \param[in] buff: Buffer handle * \return Number of bytes ready to be read */ -size_t +lwrb_sz_t lwrb_get_full(const lwrb_t* buff) { - size_t size, w, r; + lwrb_sz_t size, w, r; if (!BUF_IS_VALID(buff)) { return 0; @@ -396,9 +396,9 @@ lwrb_get_linear_block_read_address(const lwrb_t* buff) { * \param[in] buff: Buffer handle * \return Linear buffer size in units of bytes for read operation */ -size_t +lwrb_sz_t lwrb_get_linear_block_read_length(const lwrb_t* buff) { - size_t len, w, r; + lwrb_sz_t len, w, r; if (!BUF_IS_VALID(buff)) { return 0; @@ -430,9 +430,9 @@ lwrb_get_linear_block_read_length(const lwrb_t* buff) { * \param[in] len: Number of bytes to skip and mark as read * \return Number of bytes skipped */ -size_t -lwrb_skip(lwrb_t* buff, size_t len) { - size_t full, r; +lwrb_sz_t +lwrb_skip(lwrb_t* buff, lwrb_sz_t len) { + lwrb_sz_t full, r; if (!BUF_IS_VALID(buff) || len == 0) { return 0; @@ -468,9 +468,9 @@ lwrb_get_linear_block_write_address(const lwrb_t* buff) { * \param[in] buff: Buffer handle * \return Linear buffer size in units of bytes for write operation */ -size_t +lwrb_sz_t lwrb_get_linear_block_write_length(const lwrb_t* buff) { - size_t len, w, r; + lwrb_sz_t len, w, r; if (!BUF_IS_VALID(buff)) { return 0; @@ -514,9 +514,9 @@ lwrb_get_linear_block_write_length(const lwrb_t* buff) { * \param[in] len: Number of bytes to advance * \return Number of bytes advanced for write operation */ -size_t -lwrb_advance(lwrb_t* buff, size_t len) { - size_t free, w; +lwrb_sz_t +lwrb_advance(lwrb_t* buff, lwrb_sz_t len) { + lwrb_sz_t free, w; if (!BUF_IS_VALID(buff) || len == 0) { return 0; @@ -549,8 +549,8 @@ lwrb_advance(lwrb_t* buff, size_t len) { * \return `1` if \arg bts found, `0` otherwise */ uint8_t -lwrb_find(const lwrb_t* buff, const void* bts, size_t len, size_t start_offset, size_t* found_idx) { - size_t full, r, max_x; +lwrb_find(const lwrb_t* buff, const void* bts, lwrb_sz_t len, lwrb_sz_t start_offset, lwrb_sz_t* found_idx) { + lwrb_sz_t full, r, max_x; uint8_t found = 0; const uint8_t* needle = bts; @@ -567,7 +567,7 @@ lwrb_find(const lwrb_t* buff, const void* bts, size_t len, size_t start_offset, /* Max number of for loops is buff_full - input_len - start_offset of buffer length */ max_x = full - len; - for (size_t skip_x = start_offset; !found && skip_x <= max_x; ++skip_x) { + for (lwrb_sz_t skip_x = start_offset; !found && skip_x <= max_x; ++skip_x) { found = 1; /* Found by default */ /* Prepare the starting point for reading */ @@ -577,7 +577,7 @@ lwrb_find(const lwrb_t* buff, const void* bts, size_t len, size_t start_offset, } /* Search in the buffer */ - for (size_t i = 0; i < len; ++i) { + for (lwrb_sz_t i = 0; i < len; ++i) { if (buff->buff[r] != needle[i]) { found = 0; break; diff --git a/lwrb/src/lwrb/lwrb_ex.c b/lwrb/src/lwrb/lwrb_ex.c index 203eace..ab3bb83 100644 --- a/lwrb/src/lwrb/lwrb_ex.c +++ b/lwrb/src/lwrb/lwrb_ex.c @@ -53,9 +53,9 @@ * it. This operation is a read op as well as a write op. For thread-safety mutexes may be desired, * see documentation. */ -size_t -lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw) { - size_t orig_btw = btw, max_cap; +lwrb_sz_t +lwrb_overwrite(lwrb_t* buff, const void* data, lwrb_sz_t btw) { + lwrb_sz_t orig_btw = btw, max_cap; const uint8_t* d = data; if (!BUF_IS_VALID(buff) || data == NULL || btw == 0) { @@ -84,7 +84,7 @@ lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw) { * btw, otherwise we skip the operation * and only write the data. */ - size_t f = lwrb_get_free(buff); + lwrb_sz_t f = lwrb_get_free(buff); if (f < btw) { lwrb_skip(buff, btw - f); } @@ -104,9 +104,9 @@ lwrb_overwrite(lwrb_t* buff, const void* data, size_t btw) { * As well as a write op to the destination, and may update the w index. * For thread-safety mutexes may be desired, see documentation. */ -size_t +lwrb_sz_t lwrb_move(lwrb_t* dest, lwrb_t* src) { - size_t len_to_copy, len_to_copy_orig, src_full, dest_free; + lwrb_sz_t len_to_copy, len_to_copy_orig, src_full, dest_free; if (!BUF_IS_VALID(dest) || !BUF_IS_VALID(src)) { return 0; @@ -119,7 +119,7 @@ lwrb_move(lwrb_t* dest, lwrb_t* src) { /* Calculations for available length to copy is done above. We safely assume operations inside loop will properly complete. */ while (len_to_copy > 0) { - size_t max_seq_read, max_seq_write, op_len; + lwrb_sz_t max_seq_read, max_seq_write, op_len; const uint8_t* d_src; uint8_t* d_dst; @@ -134,7 +134,7 @@ lwrb_move(lwrb_t* dest, lwrb_t* src) { d_dst = lwrb_get_linear_block_write_address(dest); /* Byte by byte copy */ - for (size_t i = 0; i < op_len; ++i) { + for (lwrb_sz_t i = 0; i < op_len; ++i) { *d_dst++ = *d_src++; } From e78b832a1b5a8dd48d151a42c2d13e4f11e703a3 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 21 Oct 2023 14:47:56 +0200 Subject: [PATCH 08/20] lwrb_ex: add macro --- lwrb/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lwrb/CMakeLists.txt b/lwrb/CMakeLists.txt index 913f3ec..1ea697c 100644 --- a/lwrb/CMakeLists.txt +++ b/lwrb/CMakeLists.txt @@ -4,8 +4,9 @@ cmake_minimum_required(VERSION 3.22) add_library(lwrb INTERFACE) target_sources(lwrb PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb.c) target_include_directories(lwrb INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) + +# Register extended part add_library(lwrb_ex INTERFACE) target_sources(lwrb_ex PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb_ex.c) +target_compile_definitions(lwrb_ex INTERFACE LWRB_EXTENDED) target_include_directories(lwrb_ex INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) - -# Register other modules From 96b34fce3273b2de6c32f3bb98500db8a3fa7f79 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 21 Oct 2023 14:48:06 +0200 Subject: [PATCH 09/20] docs for lwrb types --- lwrb/src/include/lwrb/lwrb.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lwrb/src/include/lwrb/lwrb.h b/lwrb/src/include/lwrb/lwrb.h index c67cb99..8754079 100644 --- a/lwrb/src/include/lwrb/lwrb.h +++ b/lwrb/src/include/lwrb/lwrb.h @@ -48,12 +48,22 @@ extern "C" { * \{ */ -#ifdef LWRB_DISABLE_ATOMIC -typedef unsigned long lwrb_sz_atomic_t; -typedef unsigned long lwrb_sz_t; -#else +#if !defined(LWRB_DISABLE_ATOMIC) || __DOXYGEN__ #include + +/** + * \brief Atomic type for size variable. + * Default value is set to be `unsigned 32-bits` type + */ typedef atomic_ulong lwrb_sz_atomic_t; + +/** + * \brief Size variable for all library operations. + * Default value is set to be `unsigned 32-bits` type + */ +typedef unsigned long lwrb_sz_t; +#else +typedef unsigned long lwrb_sz_atomic_t; typedef unsigned long lwrb_sz_t; #endif From e8334ae4cbb9deb243f7a2e9057347f027fe7030 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 21 Oct 2023 14:48:13 +0200 Subject: [PATCH 10/20] Update documentation --- docs/user-manual/thread-safety.rst | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/user-manual/thread-safety.rst b/docs/user-manual/thread-safety.rst index 62d24b7..7aac877 100644 --- a/docs/user-manual/thread-safety.rst +++ b/docs/user-manual/thread-safety.rst @@ -4,8 +4,8 @@ Thread safety ============= Ring buffers are effectively used in embedded systems with or without operating systems. -Common problem most of implementations have is linked to multi-thread environment (when using OS) or reading/writing from/to interrupts. -This is linked to common question *What happens if I write to buffer while another thread is reading from it?* +Common problem most of implementations have, is linked to multi-thread environment (when using OS) or reading/writing from/to interrupts. +Question becomes *What happens if I write to buffer while another thread is reading from it?* One of the main requirements (beside being lightweight) of *LwRB* was to allow *read-while-write* or *write-while-read* operations. This is achieved only when there is single write entry point and single read exit point. @@ -94,3 +94,21 @@ access is granted to *read* operation while *write* operation from one thread ta .. toctree:: :maxdepth: 2 + +Atomicity +========= + +While thread-safety concepts are very important, depending on the system architecture and variable sizes (and hardware cache), +application must also ensure that all the writes and reads to the internal variables are executed in atomic manner. + +Especially critical case is when read/write from/to variable isn't ``1`` cycle on specific architecture (for instance 32-bit variable on 8-bit CPU). + +Library (in its default configuration) uses ``stdatomic`` feature from *C11* language, and relies on a compiler to properly +generate necessary calls to make sure, all reads and writes are atomic. + +.. note:: + Atomicity is required even if ring buffer is configured in *fifo* mode, with single write point and single read point. + +.. tip:: + You can disable atomic operations in the library, by defining ``LWRB_DISABLE_ATOMIC`` global macro (typically with ``-D`` compiler option). + It is then up to the developer to make sure architecture properly handles atomic operations. From 9707158a5839e9ff25cd0a5caf3c78af77f38cde Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Mon, 20 Nov 2023 22:07:17 +0100 Subject: [PATCH 11/20] Add clang-tidy --- .clang-tidy | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .clang-tidy diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..1aaa846 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,19 @@ +--- +Checks: "*, + -abseil-*, + -altera-*, + -android-*, + -fuchsia-*, + -google-*, + -llvm*, + -modernize-use-trailing-return-type, + -zircon-*, + -readability-else-after-return, + -readability-static-accessed-through-instance, + -readability-avoid-const-params-in-decls, + -cppcoreguidelines-non-private-member-variables-in-classes, + -misc-non-private-member-variables-in-classes, +" +WarningsAsErrors: '' +HeaderFilterRegex: '' +FormatStyle: none \ No newline at end of file From 82fcaa8d0bb0ecf713535b83d73766229f98a63c Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 25 Nov 2023 22:00:32 +0100 Subject: [PATCH 12/20] Add future-proof ex functions which accept flags --- dev/main.c | 37 ++++++++++++++ lwrb/src/include/lwrb/lwrb.h | 4 ++ lwrb/src/lwrb/lwrb.c | 97 +++++++++++++++++++++++++++--------- 3 files changed, 115 insertions(+), 23 deletions(-) diff --git a/dev/main.c b/dev/main.c index 95a2f92..c082d9e 100644 --- a/dev/main.c +++ b/dev/main.c @@ -57,6 +57,43 @@ main() { #undef RW_TEST } + printf("Read/Write extended test\r\n"); + { + uint8_t rw_buff[8]; + lwrb_sz_t written, read; + uint8_t success; + +#define RW_TEST(_w_exp_, _r_exp_, _success_, _rw_len_, _rw_exp_len_) \ + do { \ + printf("W ptr: %u, R ptr: %u, R/W success: %u, R/W len: %u, as_expected: %u\r\n", (unsigned)buff.w, \ + (unsigned)buff.r, (unsigned)(_success_), (unsigned)(_rw_len_), \ + (unsigned)(buff.w == (_w_exp_) && buff.r == (_r_exp_) && (_rw_len_) == (_rw_exp_len_))); \ + } while (0) + + lwrb_reset(&buff); + written = 0; + success = lwrb_write_ex(&buff, "abcdefg", 7, &written, LWRB_FLAG_WRITE_ALL); /* Write all bytes */ + RW_TEST(7, 0, success, written, 7); + success = lwrb_read_ex(&buff, rw_buff, 3, &read, LWRB_FLAG_READ_ALL); /* Read 3 bytes only */ + printf("RW FULL READ: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1)); + RW_TEST(7, 3, success, written, 7); + + /* This one shall failed, not enough memory available */ + success = lwrb_write_ex(&buff, "abcdefg", 7, &written, LWRB_FLAG_WRITE_ALL); /* Write all bytes */ + printf("RW FULL WRITE: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 0)); + + /* Read few more bytes to allow full write */ + success = lwrb_read_ex(&buff, rw_buff, 3, &read, LWRB_FLAG_READ_ALL); /* Read 3 bytes only */ + printf("RW FULL READ: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1)); + + /* Now it should go through */ + success = lwrb_write_ex(&buff, "abcdefg", 7, &written, LWRB_FLAG_WRITE_ALL); /* Write all bytes */ + printf("RW FULL WRITE: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1)); + +#undef RW_TEST + return 0; + } + printf("Overwrite test\r\n"); { #define OVERWRITE_TEST(_exp_content_, _exp_len_) \ diff --git a/lwrb/src/include/lwrb/lwrb.h b/lwrb/src/include/lwrb/lwrb.h index 8754079..0339e03 100644 --- a/lwrb/src/include/lwrb/lwrb.h +++ b/lwrb/src/include/lwrb/lwrb.h @@ -89,6 +89,10 @@ struct lwrb; */ typedef void (*lwrb_evt_fn)(struct lwrb* buff, lwrb_evt_type_t evt, lwrb_sz_t bp); +/* List of flags */ +#define LWRB_FLAG_READ_ALL ((uint16_t)0x0001) +#define LWRB_FLAG_WRITE_ALL ((uint16_t)0x0001) + /** * \brief Buffer structure */ diff --git a/lwrb/src/lwrb/lwrb.c b/lwrb/src/lwrb/lwrb.c index aabbbe9..779ec64 100644 --- a/lwrb/src/lwrb/lwrb.c +++ b/lwrb/src/lwrb/lwrb.c @@ -60,7 +60,7 @@ /** * \brief Initialize buffer handle to default values with size and buffer data array - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[in] buffdata: Pointer to memory to use as buffer data * \param[in] size: Size of `buffdata` in units of bytes * Maximum number of bytes buffer can hold is `size - 1` @@ -82,7 +82,7 @@ lwrb_init(lwrb_t* buff, void* buffdata, lwrb_sz_t size) { /** * \brief Check if buff is initialized and ready to use - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return `1` if ready, `0` otherwise */ uint8_t @@ -94,7 +94,7 @@ lwrb_is_ready(lwrb_t* buff) { * \brief Free buffer memory * \note Since implementation does not use dynamic allocation, * it just sets buffer handle to `NULL` - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance */ void lwrb_free(lwrb_t* buff) { @@ -105,7 +105,7 @@ lwrb_free(lwrb_t* buff) { /** * \brief Set event function callback for different buffer operations - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[in] evt_fn: Callback function */ void @@ -119,15 +119,37 @@ lwrb_set_evt_fn(lwrb_t* buff, lwrb_evt_fn evt_fn) { * \brief Write data to buffer. * Copies data from `data` array to buffer and marks buffer as full for maximum `btw` number of bytes * - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[in] data: Pointer to data to write into buffer * \param[in] btw: Number of bytes to write * \return Number of bytes written to buffer. * When returned value is less than `btw`, there was no enough memory available - * to copy full data array + * to copy full data array. */ lwrb_sz_t lwrb_write(lwrb_t* buff, const void* data, lwrb_sz_t btw) { + lwrb_sz_t written = 0; + + if (lwrb_write_ex(buff, data, btw, &written, 0)) { + return written; + } + return 0; +} + +/** + * \brief Write extended functionality + * + * \param buff: Ring buffer instance + * \param data: Pointer to data to write into buffer + * \param btw: Number of bytes to write + * \param bw: Output pointer to write number of bytes written + * \param flags: Optional flags. + * \ref LWRB_FLAG_WRITE_ALL: Request to write all data (up to btw). + * Will early return if no memory available + * \return `1` if write operation OK, `0` otherwise + */ +uint8_t +lwrb_write_ex(lwrb_t* buff, const void* data, lwrb_sz_t btw, lwrb_sz_t* bw, uint16_t flags) { lwrb_sz_t tocopy, free, buff_w_ptr; const uint8_t* d = data; @@ -137,10 +159,11 @@ lwrb_write(lwrb_t* buff, const void* data, lwrb_sz_t btw) { /* Calculate maximum number of bytes available to write */ free = lwrb_get_free(buff); - btw = BUF_MIN(free, btw); - if (btw == 0) { + /* If no memory, or if user wants to write ALL data but no enough space, exit early */ + if (free == 0 || (free < btw && flags & LWRB_FLAG_WRITE_ALL)) { return 0; } + btw = BUF_MIN(free, btw); buff_w_ptr = LWRB_LOAD(buff->w, memory_order_acquire); /* Step 1: Write data to linear part of buffer */ @@ -167,20 +190,45 @@ lwrb_write(lwrb_t* buff, const void* data, lwrb_sz_t btw) { LWRB_STORE(buff->w, buff_w_ptr, memory_order_release); BUF_SEND_EVT(buff, LWRB_EVT_WRITE, tocopy + btw); - return tocopy + btw; + if (bw != NULL) { + *bw = tocopy + btw; + } + return 1; } /** * \brief Read data from buffer. * Copies data from buffer to `data` array and marks buffer as free for maximum `btr` number of bytes * - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[out] data: Pointer to output memory to copy buffer data to * \param[in] btr: Number of bytes to read * \return Number of bytes read and copied to data array */ lwrb_sz_t lwrb_read(lwrb_t* buff, void* data, lwrb_sz_t btr) { + lwrb_sz_t read = 0; + + if (lwrb_read_ex(buff, data, btr, &read, 0)) { + return read; + } + return 0; +} + +/** + * \brief Write extended functionality + * + * \param buff: Ring buffer instance + * \param data: Pointer to memory to write read data from buffer + * \param btr: Number of bytes to read + * \param br: Output pointer to write number of bytes read + * \param flags: Optional flags + * \ref LWRB_FLAG_READ_ALL: Request to read all data (up to btr). + * Will early return if no enough bytes in the buffer + * \return `1` if read operation OK, `0` otherwise + */ +uint8_t +lwrb_read_ex(lwrb_t* buff, void* data, lwrb_sz_t btr, lwrb_sz_t* br, uint16_t flags) { lwrb_sz_t tocopy, full, buff_r_ptr; uint8_t* d = data; @@ -190,10 +238,10 @@ lwrb_read(lwrb_t* buff, void* data, lwrb_sz_t btr) { /* Calculate maximum number of bytes available to read */ full = lwrb_get_full(buff); - btr = BUF_MIN(full, btr); - if (btr == 0) { + if (full == 0 || (full < btr && (flags & LWRB_FLAG_READ_ALL))) { return 0; } + btr = BUF_MIN(full, btr); buff_r_ptr = LWRB_LOAD(buff->r, memory_order_acquire); /* Step 1: Read data from linear part of buffer */ @@ -220,12 +268,15 @@ lwrb_read(lwrb_t* buff, void* data, lwrb_sz_t btr) { LWRB_STORE(buff->r, buff_r_ptr, memory_order_release); BUF_SEND_EVT(buff, LWRB_EVT_READ, tocopy + btr); - return tocopy + btr; + if (br != NULL) { + *br = tocopy + btr; + } + return 1; } /** * \brief Read from buffer without changing read pointer (peek only) - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[in] skip_count: Number of bytes to skip before reading data * \param[out] data: Pointer to output memory to copy buffer data to * \param[in] btp: Number of bytes to peek @@ -275,7 +326,7 @@ lwrb_peek(const lwrb_t* buff, lwrb_sz_t skip_count, void* data, lwrb_sz_t btp) { /** * \brief Get available size in buffer for write operation - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return Number of free bytes in memory */ lwrb_sz_t @@ -321,7 +372,7 @@ lwrb_get_free(const lwrb_t* buff) { /** * \brief Get number of bytes currently available in buffer - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return Number of bytes ready to be read */ lwrb_sz_t @@ -367,7 +418,7 @@ lwrb_get_full(const lwrb_t* buff) { * \brief Resets buffer to default values. Buffer size is not modified * \note This function is not thread safe. * When used, application must ensure there is no active read/write operation - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance */ void lwrb_reset(lwrb_t* buff) { @@ -380,7 +431,7 @@ lwrb_reset(lwrb_t* buff) { /** * \brief Get linear address for buffer for fast read - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return Linear buffer start address */ void* @@ -393,7 +444,7 @@ lwrb_get_linear_block_read_address(const lwrb_t* buff) { /** * \brief Get length of linear block address before it overflows for read operation - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return Linear buffer size in units of bytes for read operation */ lwrb_sz_t @@ -426,7 +477,7 @@ lwrb_get_linear_block_read_length(const lwrb_t* buff) { * Marks data as read in the buffer and increases free memory for up to `len` bytes * * \note Useful at the end of streaming transfer such as DMA - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[in] len: Number of bytes to skip and mark as read * \return Number of bytes skipped */ @@ -452,7 +503,7 @@ lwrb_skip(lwrb_t* buff, lwrb_sz_t len) { /** * \brief Get linear address for buffer for fast read - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return Linear buffer start address */ void* @@ -465,7 +516,7 @@ lwrb_get_linear_block_write_address(const lwrb_t* buff) { /** * \brief Get length of linear block address before it overflows for write operation - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \return Linear buffer size in units of bytes for write operation */ lwrb_sz_t @@ -510,7 +561,7 @@ lwrb_get_linear_block_write_length(const lwrb_t* buff) { * * \note Useful when hardware is writing to buffer and application needs to increase number * of bytes written to buffer by hardware - * \param[in] buff: Buffer handle + * \param[in] buff: Ring buffer instance * \param[in] len: Number of bytes to advance * \return Number of bytes advanced for write operation */ From b2e49fed6e1c28059e529ce57f771120060e8e3c Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 25 Nov 2023 22:01:12 +0100 Subject: [PATCH 13/20] changelog: Update according to the changes --- CHANGELOG.md | 3 ++- dev/main.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c52292a..9ef4172 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ - Preparation for `v3.1` - Replace `size_t` with custom defined type `lwrb_sz_t` which matches atomicity requirements - `lwrb_sz_t` is by default typedef-ed as `unsigned long` -- Prepare `lwrb_write_ex` and `lwrb_read_ex` function +- Prepare `lwrb_write_ex` and `lwrb_read_ex` functions +- Implement `lwrb_write_ex` and `lwrb_read_ex` functions ## v3.0.0 diff --git a/dev/main.c b/dev/main.c index c082d9e..51de1b7 100644 --- a/dev/main.c +++ b/dev/main.c @@ -91,7 +91,6 @@ main() { printf("RW FULL WRITE: %u, as_expected: %u\r\n", (unsigned)success, (unsigned)(success == 1)); #undef RW_TEST - return 0; } printf("Overwrite test\r\n"); From 5e0999c8eddd570936b9364bba8c9d6d114fe8a0 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Fri, 8 Dec 2023 16:03:48 +0100 Subject: [PATCH 14/20] Improve docs and CMake configure_file --- docs/get-started/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 9bb83c9..3782d0e 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -65,6 +65,10 @@ Next step is to add the library to the project, by means of source files to comp * Add source files from ``lwrb/src/`` folder to toolchain build. These files are built by `C/C++` compiler. CMake configuration comes with the library, allows users to include library in the project as **subdirectory** and **library**.y * Build the project +.. tip:: + If you use the *CMake* build system, you can add the library to the project adding the ``lwshell`` + directory with ``add_directory()`` command, followed by linking the target using ``target_link_libraries()`` + Minimal example code ^^^^^^^^^^^^^^^^^^^^ From f7980bf9f15a51bf28c55476fe2924fd9dd70783 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 9 Dec 2023 11:10:20 +0100 Subject: [PATCH 15/20] Create .cmake file to allow higher flexibility of end user --- CMakeLists.txt | 2 +- lwrb/CMakeLists.txt | 11 +---------- lwrb/library.cmake | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 lwrb/library.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a6b8a4..b3d7026 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,6 @@ else() WIN32 _DEBUG CONSOLE - LWRB_DEV ) # Compiler options @@ -35,6 +34,7 @@ else() ) # Add subdir with lwrb and link to project + set(LWRB_COMPILE_DEFINITIONS LWRB_DEV) add_subdirectory(lwrb) target_link_libraries(${PROJECT_NAME} lwrb) target_link_libraries(${PROJECT_NAME} lwrb_ex) diff --git a/lwrb/CMakeLists.txt b/lwrb/CMakeLists.txt index 1ea697c..af146cc 100644 --- a/lwrb/CMakeLists.txt +++ b/lwrb/CMakeLists.txt @@ -1,12 +1,3 @@ cmake_minimum_required(VERSION 3.22) -# Register core library -add_library(lwrb INTERFACE) -target_sources(lwrb PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb.c) -target_include_directories(lwrb INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) - -# Register extended part -add_library(lwrb_ex INTERFACE) -target_sources(lwrb_ex PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb_ex.c) -target_compile_definitions(lwrb_ex INTERFACE LWRB_EXTENDED) -target_include_directories(lwrb_ex INTERFACE ${CMAKE_CURRENT_LIST_DIR}/src/include) +include(${CMAKE_CURRENT_LIST_DIR}/library.cmake) diff --git a/lwrb/library.cmake b/lwrb/library.cmake new file mode 100644 index 0000000..44a7237 --- /dev/null +++ b/lwrb/library.cmake @@ -0,0 +1,28 @@ +# Library core sources +set(lwrb_core_SRCS + ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb.c +) + +# Library extended sources +set(lwrb_ex_SRCS + ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb_ex.c +) + +# Setup include directories +set(lwrb_include_DIRS + ${CMAKE_CURRENT_LIST_DIR}/src/include +) + +# Register library to the system +add_library(lwrb) +target_sources(lwrb PUBLIC ${lwrb_core_SRCS}) +target_include_directories(lwrb PUBLIC ${lwrb_include_DIRS}) +target_compile_options(lwrb PUBLIC ${LWRB_COMPILE_OPTIONS}) +target_compile_definitions(lwrb PUBLIC ${LWRB_COMPILE_DEFINITIONS}) + +# Register extended part +add_library(lwrb_ex) +target_sources(lwrb_ex PUBLIC ${lwrb_ex_SRCS}) +target_include_directories(lwrb_ex PUBLIC ${lwrb_include_DIRS}) +target_compile_options(lwrb_ex PUBLIC ${LWRB_COMPILE_OPTIONS}) +target_compile_definitions(lwrb_ex PUBLIC ${LWRB_COMPILE_DEFINITIONS} LWRB_EXTENDED) From 33d8dd0de601f3d1b42b8dff43bd1584b86c055c Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 9 Dec 2023 16:49:23 +0100 Subject: [PATCH 16/20] Improve the cmake documentation --- docs/get-started/index.rst | 16 +++++++++++----- lwrb/library.cmake | 10 ++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/get-started/index.rst b/docs/get-started/index.rst index 3782d0e..fb6293d 100644 --- a/docs/get-started/index.rst +++ b/docs/get-started/index.rst @@ -58,17 +58,23 @@ Add library to project ^^^^^^^^^^^^^^^^^^^^^^ At this point it is assumed that you have successfully download library, either cloned it or from releases page. -Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path +Next step is to add the library to the project, by means of source files to compiler inputs and header files in search path. + +*CMake* is the main supported build system. Package comes with the ``CMakeLists.txt`` and ``library.cmake`` files, both located in the ``lwrb`` directory: + +* ``CMakeLists.txt``: Is a wrapper and only includes ``library.cmake`` file. It is used if target application uses ``add_subdirectory`` and then uses ``target_link_libraries`` to include the library in the project +* ``library.cmake``: It is a fully configured set of variables. User must use ``include(path/to/library.cmake)`` to include the library and must manually add files/includes to the final target + +.. tip:: + Open ``library.cmake`` file and manually analyze all the possible variables you can set for full functionality. + +If you do not use the *CMake*, you can do the following: * Copy ``lwrb`` folder to your project, it contains library files * Add ``lwrb/src/include`` folder to `include path` of your toolchain. This is where `C/C++` compiler can find the files during compilation process. Usually using ``-I`` flag * Add source files from ``lwrb/src/`` folder to toolchain build. These files are built by `C/C++` compiler. CMake configuration comes with the library, allows users to include library in the project as **subdirectory** and **library**.y * Build the project -.. tip:: - If you use the *CMake* build system, you can add the library to the project adding the ``lwshell`` - directory with ``add_directory()`` command, followed by linking the target using ``target_link_libraries()`` - Minimal example code ^^^^^^^^^^^^^^^^^^^^ diff --git a/lwrb/library.cmake b/lwrb/library.cmake index 44a7237..3e14f7a 100644 --- a/lwrb/library.cmake +++ b/lwrb/library.cmake @@ -1,3 +1,13 @@ +# +# This file provides set of variables for end user +# and also generates one (or more) libraries, that can be added to the project using target_link_libraries(...) +# +# Before this file is included to the root CMakeLists file (using include() function), user can set some variables: +# +# LWRB_COMPILE_OPTIONS: If defined, it provide compiler options for generated library. +# LWRB_COMPILE_DEFINITIONS: If defined, it provides "-D" definitions to the library build +# + # Library core sources set(lwrb_core_SRCS ${CMAKE_CURRENT_LIST_DIR}/src/lwrb/lwrb.c From 6fe0243a479284d31f5fac3c27ce11267b34e651 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 9 Dec 2023 17:06:40 +0100 Subject: [PATCH 17/20] Add AUTHORS file --- AUTHORS | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..f4df17b --- /dev/null +++ b/AUTHORS @@ -0,0 +1,9 @@ +Tilen Majerle +Tilen Majerle +Jaedeok Kim +Thomas Devoogdt +LinJieqiang <517503838@qq.com> +jnz86 +Junde Yhi +Jackistang +Tofik Sonono \ No newline at end of file From 11412bfb3291555ca203014acac5506fcb37babb Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Sat, 9 Dec 2023 17:13:47 +0100 Subject: [PATCH 18/20] Add authors in the docs file --- docs/authors/index.rst | 8 ++++++++ docs/index.rst | 1 + 2 files changed, 9 insertions(+) create mode 100644 docs/authors/index.rst diff --git a/docs/authors/index.rst b/docs/authors/index.rst new file mode 100644 index 0000000..4031a8c --- /dev/null +++ b/docs/authors/index.rst @@ -0,0 +1,8 @@ +.. _authors: + +Authors +======= + +List of authors and contributors to the library + +.. literalinclude:: ../../AUTHORS \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 7214a96..546ebe4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -76,6 +76,7 @@ Table of contents tips-tricks/index api-reference/index changelog/index + authors/index .. toctree:: :maxdepth: 2 From 2e52cd16c769bbe684599211001c7f217779fd63 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 21 Dec 2023 08:12:11 +0100 Subject: [PATCH 19/20] ex: remove error, do not build if development mode isn't enabled --- lwrb/src/lwrb/lwrb_ex.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lwrb/src/lwrb/lwrb_ex.c b/lwrb/src/lwrb/lwrb_ex.c index ab3bb83..ef4e21d 100644 --- a/lwrb/src/lwrb/lwrb_ex.c +++ b/lwrb/src/lwrb/lwrb_ex.c @@ -33,13 +33,13 @@ */ #include "lwrb/lwrb.h" +#if defined(LWRB_DEV) + +/* Do not build if development mode isn't enabled */ + #define BUF_IS_VALID(b) ((b) != NULL && (b)->buff != NULL && (b)->size > 0) #define BUF_MIN(x, y) ((x) < (y) ? (x) : (y)) -#ifndef LWRB_DEV -#error "This file needs development & extensive tests - not to be used!" -#endif - /** * \brief Writes data to buffer with overwrite function, if no enough space to hold * complete input data object. @@ -148,3 +148,5 @@ lwrb_move(lwrb_t* dest, lwrb_t* src) { } return len_to_copy_orig; } + +#endif /* defined(LWRB_DEV) */ From c7fe6fd388a6dede8fe034d288f3f31cf7e7be44 Mon Sep 17 00:00:00 2001 From: Tilen Majerle Date: Thu, 21 Dec 2023 08:14:19 +0100 Subject: [PATCH 20/20] Version 3.1.0 --- CHANGELOG.md | 5 ++++- library.json | 2 +- lwrb/src/include/lwrb/lwrb.h | 2 +- lwrb/src/lwrb/lwrb.c | 2 +- lwrb/src/lwrb/lwrb_ex.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ef4172..bc668b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,14 @@ ## Develop +## v3.1.0 + - Preparation for `v3.1` - Replace `size_t` with custom defined type `lwrb_sz_t` which matches atomicity requirements - `lwrb_sz_t` is by default typedef-ed as `unsigned long` - Prepare `lwrb_write_ex` and `lwrb_read_ex` functions - Implement `lwrb_write_ex` and `lwrb_read_ex` functions +- Fix `_ex` module throwing an error for Platform.IO ## v3.0.0 @@ -14,7 +17,7 @@ - Add `lwrb_move` and `lwrb_overwrite` - Fix `lwrb_find` which failed to properly search for tokens at corner cases -## v3.0.0-RC1 +## v3.1.0-RC1 - Split CMakeLists.txt files between library and executable - Change license year to 2022 diff --git a/library.json b/library.json index f3b65e3..a89971a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "LwRB", - "version": "3.0.0", + "version": "3.1.0", "description": "Lightweight general purpose ring buffer with optimizations for embedded systems", "keywords": "buffer, ring buffer, library, rb, cyclic", "repository": { diff --git a/lwrb/src/include/lwrb/lwrb.h b/lwrb/src/include/lwrb/lwrb.h index 0339e03..6da7a20 100644 --- a/lwrb/src/include/lwrb/lwrb.h +++ b/lwrb/src/include/lwrb/lwrb.h @@ -29,7 +29,7 @@ * This file is part of LwRB - Lightweight ring buffer library. * * Author: Tilen MAJERLE - * Version: v3.0.0-rc1 + * Version: v3.1.0 */ #ifndef LWRB_HDR_H #define LWRB_HDR_H diff --git a/lwrb/src/lwrb/lwrb.c b/lwrb/src/lwrb/lwrb.c index 779ec64..5e13468 100644 --- a/lwrb/src/lwrb/lwrb.c +++ b/lwrb/src/lwrb/lwrb.c @@ -29,7 +29,7 @@ * This file is part of LwRB - Lightweight ring buffer library. * * Author: Tilen MAJERLE - * Version: v3.0.0 + * Version: v3.1.0 */ #include "lwrb/lwrb.h" diff --git a/lwrb/src/lwrb/lwrb_ex.c b/lwrb/src/lwrb/lwrb_ex.c index ef4e21d..9893759 100644 --- a/lwrb/src/lwrb/lwrb_ex.c +++ b/lwrb/src/lwrb/lwrb_ex.c @@ -29,7 +29,7 @@ * This file is part of LwRB - Lightweight ring buffer library. * * Author: Tilen MAJERLE - * Version: v3.0.0-rc1 + * Version: v3.1.0 */ #include "lwrb/lwrb.h"