From 87906956885f0e551b92e2cf3a2789e8f27b0929 Mon Sep 17 00:00:00 2001 From: Attila Body Date: Mon, 9 Jun 2025 17:21:52 +0200 Subject: [PATCH] Use ring_buffer for console untested --- components/app/src/application.cpp | 78 +++++--- components/f4ll/inc/f4ll/console_handler.h | 14 +- components/f4ll/inc/f4ll/ringbuffer.h | 218 +++++++++++++++++++++ components/f4ll/src/console_handler.cpp | 75 ++++--- 4 files changed, 323 insertions(+), 62 deletions(-) create mode 100644 components/f4ll/inc/f4ll/ringbuffer.h diff --git a/components/app/src/application.cpp b/components/app/src/application.cpp index 253f1bb..3c044f2 100644 --- a/components/app/src/application.cpp +++ b/components/app/src/application.cpp @@ -4,14 +4,12 @@ * Created on: Oct 28, 2019 * Author: abody */ -#ifdef USE_CPLUSPLUS - -#include "f4ll/consolehandler.h" +#include "f4ll/console_handler.h" #include "f4ll/crc_handler.h" -#include "f4ll/irqlock.h" -#include "f4ll/memcpydma.h" -#include "f4ll/packetusart.h" -#include "f4ll/strutil.h" +#include "f4ll/irq_lock.h" +#include "f4ll/memcpy_dma.h" +#include "f4ll/packet_usart.h" +#include "f4ll/str_util.h" #include #include @@ -20,16 +18,42 @@ extern "C" { #include "globals.h" #include "config.h" } -#include "globals_cpp.h" +#include "globals.h" #define PACKAGE_DELAY_MS 0 #define STATS_DELAY_MS 1000 - #define ADDINFO(b,s,u) \ b += strcpy_ex(b,s); \ b += uitodec(b,u); +void PrintStats(f4ll::console_handler &con, uint8_t id, f4ll::packet_usart &usart) +{ + // char ids[] = " : "; + // char *buffer = m_buffer; + // packet_usart::stats const &stats = usart.get_stats(); + + // ids[0] = id + '0'; + // buffer += strcpy_ex(buffer, ids); + // ADDINFO(buffer, " s: ", stats.sent); + // ADDINFO(buffer, " r: ", stats.rcvd); + // ADDINFO(buffer, " sk: ", stats.skiped); + // ADDINFO(buffer, " or: ", stats.overrun); + // ADDINFO(buffer, " he: ", stats.hdr_error); + // ADDINFO(buffer, " pe: ", stats.payload_errror); + // buffer += strcpy_ex(buffer, ",0x"); + // buffer += uitohex(buffer, stats.pep1, 8); + // buffer += strcpy_ex(buffer, ",0x"); + // buffer += uitohex(buffer, stats.pep2, 8); + // ADDINFO(buffer, " rde: ", stats.rx_dma_error); + // ADDINFO(buffer, " tde: ", stats.tx_dma_error); + // ADDINFO(buffer, " pmh: ", stats.premature_hdr); + // ADDINFO(buffer, " pmp: ", stats.premature_payload); + // buffer += strcpy_ex(buffer, "\r\n"); + + // setup_transmit(m_buffer, buffer - m_buffer + 1); +} + extern "C" void MainLoop() { uint8_t const text2Send[] __attribute__((aligned(16))) = @@ -37,17 +61,17 @@ extern "C" void MainLoop() "--------------------------------------------\r\n\0\0\0"; - f4ll::MemcpyDma::Init(MEMCPY_DMA_ENGINE, MEMCPY_DMA_STREAM); - f4ll::crc_handler::Init(DMA2, LL_DMA_STREAM_4); - f4ll::ConsoleHandler::Init(UART4, CONSOLE_DMA_ENGINE, 0u, CONSOLE_TX_DMA_STREAM); + f4ll::memcpy_dma::init(MEMCPY_DMA_ENGINE, MEMCPY_DMA_STREAM); + f4ll::crc_handler::init(DMA2, LL_DMA_STREAM_4); + f4ll::console_handler::init(UART4, CONSOLE_DMA_ENGINE, 0u, CONSOLE_TX_DMA_STREAM); - f4ll::PacketUsart u1{ USART1, DMA2, LL_DMA_STREAM_2, LL_DMA_STREAM_7 }; - f4ll::PacketUsart u2{ USART2, DMA1, LL_DMA_STREAM_5, LL_DMA_STREAM_6 }; - f4ll::PacketUsart u3{ USART3, DMA1, LL_DMA_STREAM_1, LL_DMA_STREAM_3 }; - f4ll::PacketUsart u6{ USART6, DMA2, LL_DMA_STREAM_1, LL_DMA_STREAM_6 }; + f4ll::packet_usart u1{ USART1, DMA2, LL_DMA_STREAM_2, LL_DMA_STREAM_7 }; + f4ll::packet_usart u2{ USART2, DMA1, LL_DMA_STREAM_5, LL_DMA_STREAM_6 }; + f4ll::packet_usart u3{ USART3, DMA1, LL_DMA_STREAM_1, LL_DMA_STREAM_3 }; + f4ll::packet_usart u6{ USART6, DMA2, LL_DMA_STREAM_1, LL_DMA_STREAM_6 }; - f4ll::PacketUsart * usarts[] = { &u1, &u2, &u3, &u6 }; - f4ll::PacketUsart **dst = g_usarts; + f4ll::packet_usart * usarts[] = { &u1, &u2, &u3, &u6 }; + f4ll::packet_usart **dst = g_usarts; for(auto usart: usarts) *dst++ = usart; @@ -67,7 +91,7 @@ extern "C" void MainLoop() lastStatsTick = HAL_GetTick(); for(auto u : g_usarts) - u->SetupReceive(); + u->setup_receive(); for(;;) { uint32_t tick = HAL_GetTick(); @@ -77,22 +101,22 @@ extern "C" void MainLoop() prevSentTick += PACKAGE_DELAY_MS; for(auto u : g_usarts) { - if(!u->IsTxBusy() && send) { + if(!u->is_tx_busy() && send) { //DIAG_ENTER_BUSY(); auto len = sizeof(text2Send) - 1 - (rand() & randmask); - f4ll::MemcpyDma::Instance().Copy(u->GetTxPacketBuffer(), text2Send, len); - u->PostPacket(nullptr, len); + f4ll::memcpy_dma::instance().copy(u->get_tx_packet_buffer(), text2Send, len); + u->post_packet(nullptr, len); //DIAG_EXIT_BUSY(); } for(uint16_t rIdx = 0; rIdx < 2; ++rIdx) - if(u->IsRxBusy((bool)rIdx) || u->IsRxFailed(rIdx)) { - u->GetRxPacketBuffer(rIdx); + if(u->is_rx_busy((bool)rIdx) || u->is_rx_failed(rIdx)) { + u->get_rx_packet_buffer(rIdx); // ... - u->RxProcessed((bool)rIdx); + u->rx_processed((bool)rIdx); } } if(tick - lastStatsTick > STATS_DELAY_MS) { - f4ll::ConsoleHandler::Instance().PrintStats(statId, *g_usarts[statId]); + PrintStats(f4ll::console_handler::instance(), statId, *g_usarts[statId]); lastStatsTick += STATS_DELAY_MS; ++statId; if(statId >= sizeof(g_usarts) / sizeof(g_usarts[0])) @@ -105,5 +129,3 @@ extern "C" void MainLoop() // } } } - -#endif // USE_CPLUSPLUS diff --git a/components/f4ll/inc/f4ll/console_handler.h b/components/f4ll/inc/f4ll/console_handler.h index 34da08c..9972539 100644 --- a/components/f4ll/inc/f4ll/console_handler.h +++ b/components/f4ll/inc/f4ll/console_handler.h @@ -5,10 +5,10 @@ * Author: abody */ -#ifndef LL_CONSOLEHANDLER_H_ -#define LL_CONSOLEHANDLER_H_ +#pragma once #include +#include #include namespace f4ll { @@ -18,7 +18,9 @@ class console_handler : public usart_core, public singleton friend class singleton; public: - void PrintStats(uint8_t id, packet_usart &usart); + void print(char const *s); + void flush(); + size_t append(char const *s); private: console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); @@ -35,10 +37,8 @@ private: virtual void tx_dma_half_transfer(void) override; virtual void tx_dma_error(dma_helper::dma_error_type reason) override; - char m_buffer[128]; - uint16_t m_used = 0; + ringbuffer<128> m_tx_buffer; + iringbuffer::size_type m_in_flight_size = 0; }; } /* namespace f4ll */ - -#endif /* LL_CONSOLEHANDLER_H_ */ diff --git a/components/f4ll/inc/f4ll/ringbuffer.h b/components/f4ll/inc/f4ll/ringbuffer.h new file mode 100644 index 0000000..acf39d1 --- /dev/null +++ b/components/f4ll/inc/f4ll/ringbuffer.h @@ -0,0 +1,218 @@ +/* + * ringbuffer.h + * + * Created on: May 31, 2025 + * Author: Attila Body + */ + +#pragma once + +#include +#include +#include + +namespace f4ll { + +class iringbuffer +{ +public: + using size_type = size_t; + + /// @brief Copies data to the ring buffer (without committing it) + /// @param data Pointer to the data to copy + /// @param len Length of the data to copy + /// @retval Length of the data copied (differs when not all data can fit) + virtual size_type put(uint8_t const *data, size_type len) = 0; + + /// @brief Commits the data already placed into the buffer and notifies the + /// consumer about it's availability + virtual void commit() = 0; + + /// @brief Waits until all the data from the ring buffer gets consumed. + // void flush(); + + /// @brief Gets a pointer to the next chunk of committed data in the buffer + /// without registering the consumption. + /// The caller should also call report_consumption using the returned + /// chunk length after it finished processing the data. + /// @param[in] len_requested Length of the data requested from the buffer. + /// The length of the actual data provided + /// might be actually smaller (because either reaching the end of + /// the buffer or not enough data in the buffer). + /// @param[out] data Receives a pointer to the first byte of the available + /// data in the buffer + /// @param[out] len Receives the length of the chunk available in the buffer. + /// Will not exceed len_requested. + /// @retval true if the buffer has more available data, false otherwise. + virtual bool get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const = 0; + + /// @brief Marks the chunk returned by ringbuffer_GetChunk as available. + /// @param consumed The length of the chunk as returned by + /// ringbuffer_GetChunk(..., len) + virtual void consumed(size_type len) = 0; + + /// @brief Returns the number of uncommited bytes in the ring buffer. + virtual size_type uncommited() const = 0; + + /// @brief Returns the number of commited bytes in the ring buffer. + virtual size_type commited() const = 0; + + /// @brief Discards the uncommited data in the ring buffer. + virtual void discard() = 0; + + /// @brief Returns the size of the internal buffer. + /// One byte in the buffer is always reserved as separator + virtual size_type size() const = 0; + + /// @brief Returns the size of the used place in the buffer + // (including non-commited data) + virtual size_type used() const = 0; + + /// @brief Returns the free storage capacity of the buffer + virtual size_type unused() const = 0; +}; + +template class ringbuffer : public iringbuffer +{ +public: + ringbuffer() = default; + + size_type put(uint8_t const *data, size_type len) override; + void commit() override; + bool get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const override; + void consumed(size_type len) override; + size_type uncommited() const override; + size_type commited() const override; + void discard() override; + size_type size() const override; + size_type used() const override; + size_type unused() const override; + +private: + uint8_t m_buffer[SZ]; //!< Data bufer + size_type m_head = 0; //!< Write position + size_type m_head_shadow = 0; //!< Shadowed write position for collecting data + //!< before committing it + size_type m_tail = 0; //!< Read position + + size_type marker_diff(size_type m1, size_type m2) const; +}; + +// +template iringbuffer::size_type ringbuffer::put(uint8_t const *data, size_type len) +{ + size_type chunk1 = 0; + size_type chunk2 = 0; + + if (!data || !len) { + return 0; + } + + size_type max_len = unused(); + len = len < max_len ? len : max_len; + + chunk1 = sizeof(m_buffer) - m_head_shadow; + if (chunk1 >= len) { + chunk1 = len; + } else { + chunk2 = len - chunk1; + } + + std::memcpy(m_buffer + m_head_shadow, data, chunk1); + m_head_shadow += chunk1; + if (m_head_shadow == sizeof(m_buffer)) { + m_head_shadow = 0; + } + + if (chunk2) { + std::memcpy(m_buffer, data + chunk1, chunk2); + m_head_shadow += chunk2; + if (m_head_shadow == sizeof(m_buffer)) { + m_head_shadow = 0; + } + } + + return len; +} + +template void ringbuffer::commit() +{ + m_head = m_head_shadow; +}; + +template bool ringbuffer::get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const +{ + if (!len_requested) { + return false; + } + + size_type head = m_head; + size_type tail = m_tail; + size_type chunk_size = head >= tail ? head - tail : sizeof(m_buffer) - tail; + + if (!chunk_size) { + len = 0; + return false; + } + + if (chunk_size > len_requested) { + chunk_size = len_requested; + } + data = m_buffer + tail; + len = chunk_size; + + tail += chunk_size; + if (tail == sizeof(m_buffer)) { + tail = 0; + } + + return tail != head; +} + +template void ringbuffer::consumed(size_type len) +{ + if (!len) { + return; + } + m_tail += len; + if (m_tail == sizeof(m_buffer)) { + m_tail = 0; + } +} + +template iringbuffer::size_type ringbuffer::uncommited() const +{ + return marker_diff(m_head_shadow, m_head); +} + +template iringbuffer::size_type ringbuffer::commited() const +{ + return marker_diff(m_head, m_tail); +} + +template void ringbuffer::discard() +{ + m_head_shadow = m_head; +} + +template iringbuffer::size_type ringbuffer::size() const +{ + return SZ; +} + +template iringbuffer::size_type ringbuffer::used() const +{ + return marker_diff(m_head_shadow, m_tail); +} + +template iringbuffer::size_type ringbuffer::unused() const +{ + return SZ - used() - 1; +} + +template iringbuffer::size_type ringbuffer::marker_diff(size_type m1, size_type m2) const +{ + return (m1 >= m2) ? (m1 - m2) : (SZ - m2 + m1); +} + +} // namespace f1ll \ No newline at end of file diff --git a/components/f4ll/src/console_handler.cpp b/components/f4ll/src/console_handler.cpp index 02c990f..694e107 100644 --- a/components/f4ll/src/console_handler.cpp +++ b/components/f4ll/src/console_handler.cpp @@ -6,8 +6,11 @@ */ #include +#include #include +#include + namespace f4ll { console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx) @@ -17,7 +20,19 @@ console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_ void console_handler::receiver_idle(void) {} -void console_handler::transmission_complete(void) {} +void console_handler::transmission_complete(void) +{ + m_tx_buffer.consumed(m_in_flight_size); + if (m_tx_buffer.commited()) { + uint8_t const *chunk; + m_tx_buffer.get_chunk(m_tx_buffer.size(), chunk, m_in_flight_size); + if (m_in_flight_size) { + setup_transmit(chunk, m_in_flight_size); + } + } else { + m_in_flight_size = 0; + } +} void console_handler::framing_error(void) {} @@ -45,35 +60,41 @@ void console_handler::tx_dma_error(dma_helper::dma_error_type reason) (void)reason; } -#define ADDINFO(b, s, u) \ - b += strcpy_ex(b, s); \ - b += uitodec(b, u); - -void console_handler::PrintStats(uint8_t id, packet_usart &usart) +size_t console_handler::append(char const *s) { - char ids[] = " : "; - char *buffer = m_buffer; - packet_usart::stats const &stats(usart.get_stats()); + size_t len = strlen(s); + if (!len) { + return 0; + } + return len - m_tx_buffer.put(reinterpret_cast(s), len); +} - ids[0] = id + '0'; - buffer += strcpy_ex(buffer, ids); - ADDINFO(buffer, " s: ", stats.sent); - ADDINFO(buffer, " r: ", stats.rcvd); - ADDINFO(buffer, " sk: ", stats.skiped); - ADDINFO(buffer, " or: ", stats.overrun); - ADDINFO(buffer, " he: ", stats.hdr_error); - ADDINFO(buffer, " pe: ", stats.payload_errror); - buffer += strcpy_ex(buffer, ",0x"); - buffer += uitohex(buffer, stats.pep1, 8); - buffer += strcpy_ex(buffer, ",0x"); - buffer += uitohex(buffer, stats.pep2, 8); - ADDINFO(buffer, " rde: ", stats.rx_dma_error); - ADDINFO(buffer, " tde: ", stats.tx_dma_error); - ADDINFO(buffer, " pmh: ", stats.premature_hdr); - ADDINFO(buffer, " pmp: ", stats.premature_payload); - buffer += strcpy_ex(buffer, "\r\n"); +void console_handler::flush() +{ + bool busy; - setup_transmit(m_buffer, buffer - m_buffer + 1); + if (!m_tx_buffer.uncommited()) { + return; + } + m_tx_buffer.commit(); + { + irq_lock l; + busy = m_in_flight_size != 0; + } + if (busy) { + return; + } + uint8_t const *chunk; + m_tx_buffer.get_chunk(m_tx_buffer.size(), chunk, m_in_flight_size); + if (m_in_flight_size) { + setup_transmit(chunk, m_in_flight_size); + } +} + +void console_handler::print(char const *s) +{ + append(s); + flush(); } } /* namespace f4ll */