Squash me

This commit is contained in:
Attila Body 2025-06-12 00:10:30 +02:00
parent b2eee97903
commit fb4aae99bf
Signed by: abody
GPG key ID: BD0C6214E68FB5CF
5 changed files with 95 additions and 29 deletions

View file

@ -18,12 +18,21 @@ class console_handler : public usart_core, public initialized_singleton<console_
friend class initialized_singleton<console_handler>; friend class initialized_singleton<console_handler>;
public: public:
using size_type = iringbuffer::size_type;
class iconsole_input
{
public:
virtual void input_available(size_type len) = 0;
};
void print(char const *s); void print(char const *s);
void flush(); void flush();
size_t append(char const *s); size_t append(char const *s);
private: private:
console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx); console_handler(
USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, uint8_t *rx_buffer, size_type x_buffer_size,
uint8_t *tx_buffer, size_type tx_buffer_size, iconsole_input *rx_callback);
// LL_UsartCore pure virtual function implementations // LL_UsartCore pure virtual function implementations
virtual void receiver_idle(void) override; virtual void receiver_idle(void) override;
@ -37,8 +46,12 @@ private:
virtual void tx_dma_half_transfer(void) override; virtual void tx_dma_half_transfer(void) override;
virtual void tx_dma_error(dma_helper::dma_error_type reason) override; virtual void tx_dma_error(dma_helper::dma_error_type reason) override;
ringbuffer<128> m_tx_buffer; ringbuffer_ext m_tx_buffer;
iringbuffer::size_type m_in_flight_size = 0; size_type m_bytes_sent = 0;
ringbuffer_ext m_rx_buffer;
size_type m_bytes_requested = 0;
iconsole_input *m_rx_callback;
}; };
} /* namespace f4ll */ } /* namespace f4ll */

View file

@ -35,22 +35,30 @@ public:
/// without registering the consumption. /// without registering the consumption.
/// The caller should also call report_consumption using the returned /// The caller should also call report_consumption using the returned
/// chunk length after it finished processing the data. /// 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 /// @param[out] data Receives a pointer to the first byte of the available
/// data in the buffer /// data in the buffer
/// @param[out] len Receives the length of the chunk available in the buffer. /// @param[out] len Receives the length of the chunk available in the buffer.
/// Will not exceed len_requested. /// Will not exceed len_requested.
/// @retval true if the buffer has more available data, false otherwise. /// @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; virtual bool get_chunk(uint8_t const *&data, size_type &len) const = 0;
/// @brief Marks the chunk returned by ringbuffer_GetChunk as available. /// @brief Marks the chunk returned by ringbuffer_GetChunk as available.
/// @param consumed The length of the chunk as returned by /// @param consumed The length of the chunk as returned by
/// ringbuffer_GetChunk(..., len) /// ringbuffer_GetChunk(..., len)
virtual void consumed(size_type len) = 0; virtual void consumed(size_type len) = 0;
/// @brief Gets a pointer to the next free chunk in the buffer
/// @retval Pointer to the beginning of the next free buffer chmemory area
/// @param[out] len Receives the length of the returned buffer area.
virtual uint8_t *get_free_chunk(size_type &len) = 0;
/// @brief Registers the data written in the free buffer chunk.
/// IMPORTANT: Do not call put() after start modifying the buffer
/// returned by get_free_chunk() before registering the written data by
/// calling supplied()
/// @param len The length of the data written in the buffer
virtual bool produced(size_type len) = 0;
/// @brief Returns the number of uncommited bytes in the ring buffer. /// @brief Returns the number of uncommited bytes in the ring buffer.
virtual size_type uncommited() const = 0; virtual size_type uncommited() const = 0;
@ -80,8 +88,13 @@ public:
size_type put(uint8_t const *data, size_type len) override; size_type put(uint8_t const *data, size_type len) override;
void commit() override; void commit() override;
bool get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const override;
bool get_chunk(uint8_t const *&data, size_type &len) const override;
void consumed(size_type len) override; void consumed(size_type len) override;
uint8_t *get_free_chunk(size_type &len) override;
bool produced(size_type len) override;
size_type uncommited() const override; size_type uncommited() const override;
size_type commited() const override; size_type commited() const override;
void discard() override; void discard() override;
@ -98,6 +111,7 @@ private:
size_type m_tail = 0; //!< Read position size_type m_tail = 0; //!< Read position
size_type marker_diff(size_type m1, size_type m2) const; size_type marker_diff(size_type m1, size_type m2) const;
size_type max_chunk_len() const;
}; };
// //

View file

@ -31,6 +31,7 @@ protected:
dma_helper m_tx_dma; dma_helper m_tx_dma;
private: private:
// these functions are called from interrup context!
virtual void receiver_idle(void) = 0; virtual void receiver_idle(void) = 0;
virtual void transmission_complete(void) = 0; virtual void transmission_complete(void) = 0;
virtual void framing_error(void) = 0; virtual void framing_error(void) = 0;

View file

@ -5,6 +5,7 @@
* Author: abody * Author: abody
*/ */
#include <cstddef>
#include <f4ll/console_handler.h> #include <f4ll/console_handler.h>
#include <f4ll/irq_lock.h> #include <f4ll/irq_lock.h>
#include <f4ll/str_util.h> #include <f4ll/str_util.h>
@ -13,24 +14,39 @@
namespace f4ll { namespace f4ll {
console_handler::console_handler(USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx) console_handler::console_handler(
: usart_core(usart, dma, stream_rx, stream_tx) USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, uint8_t *rx_buffer, size_type rx_buffer_size,
uint8_t *tx_buffer, size_type tx_buffer_size, iconsole_input *rx_callback)
: usart_core(usart, dma, stream_rx, stream_tx),
m_tx_buffer(tx_buffer, tx_buffer_size),
m_rx_buffer(rx_buffer, rx_buffer_size),
m_rx_callback(rx_callback)
{ {
} }
void console_handler::receiver_idle(void) {} void console_handler::receiver_idle(void)
{
if (!m_rx_callback) {
return;
}
uint16_t rcvd_bytes = m_bytes_requested - LL_DMA_GetDataLength(m_rx_dma.get_dma(), m_rx_dma.get_stream());
size_type len;
uint8_t const *data;
bool more_data = m_rx_buffer.get_chunk(data, len);
m_rx_callback->input_available(len);
}
void console_handler::transmission_complete(void) void console_handler::transmission_complete(void)
{ {
m_tx_buffer.consumed(m_in_flight_size); m_tx_buffer.consumed(m_bytes_sent);
if (m_tx_buffer.commited()) { if (m_tx_buffer.commited()) {
uint8_t const *chunk; uint8_t const *chunk;
m_tx_buffer.get_chunk(m_tx_buffer.size(), chunk, m_in_flight_size); m_tx_buffer.get_chunk(chunk, m_bytes_sent);
if (m_in_flight_size) { if (m_bytes_sent) {
setup_transmit(chunk, m_in_flight_size); setup_transmit(chunk, m_bytes_sent);
} }
} else { } else {
m_in_flight_size = 0; m_bytes_sent = 0;
} }
} }
@ -76,14 +92,14 @@ void console_handler::flush()
} }
m_tx_buffer.commit(); m_tx_buffer.commit();
if (m_in_flight_size) { if (m_bytes_sent) {
return; return;
} }
uint8_t const *chunk; uint8_t const *chunk;
m_tx_buffer.get_chunk(m_tx_buffer.size(), chunk, m_in_flight_size); m_tx_buffer.get_chunk(chunk, m_bytes_sent);
if (m_in_flight_size) { if (m_bytes_sent) {
setup_transmit(chunk, m_in_flight_size); setup_transmit(chunk, m_bytes_sent);
} }
} }

View file

@ -49,12 +49,8 @@ void ringbuffer_ext::commit()
m_head = m_head_shadow; m_head = m_head_shadow;
} }
bool ringbuffer_ext::get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const bool ringbuffer_ext::get_chunk(uint8_t const *&data, size_type &len) const
{ {
if (!len_requested) {
return false;
}
size_type head = m_head; size_type head = m_head;
size_type tail = m_tail; size_type tail = m_tail;
size_type chunk_size = head >= tail ? head - tail : m_bsize - tail; size_type chunk_size = head >= tail ? head - tail : m_bsize - tail;
@ -64,9 +60,6 @@ bool ringbuffer_ext::get_chunk(size_type len_requested, uint8_t const *&data, si
return tail != head; return tail != head;
} }
if (chunk_size > len_requested) {
chunk_size = len_requested;
}
data = m_buffer + tail; data = m_buffer + tail;
len = chunk_size; len = chunk_size;
@ -89,6 +82,35 @@ void ringbuffer_ext::consumed(size_type len)
} }
} }
iringbuffer::size_type ringbuffer_ext::max_chunk_len() const
{
if (m_tail <= m_head_shadow) {
return m_bsize - m_head_shadow;
} else {
return m_tail - m_head_shadow - 1;
}
}
uint8_t *ringbuffer_ext::get_free_chunk(size_type &len)
{
len = max_chunk_len();
return m_buffer + m_head_shadow;
}
bool ringbuffer_ext::produced(size_type len)
{
size_type max_len = max_chunk_len();
if (len > max_len) {
return false;
}
m_head_shadow += len;
if (m_head_shadow == m_bsize) {
m_head_shadow = 0;
}
return true;
}
iringbuffer::size_type ringbuffer_ext::uncommited() const iringbuffer::size_type ringbuffer_ext::uncommited() const
{ {
return marker_diff(m_head_shadow, m_head); return marker_diff(m_head_shadow, m_head);