Compare commits
4 commits
28502efcb4
...
fb4aae99bf
Author | SHA1 | Date | |
---|---|---|---|
fb4aae99bf | |||
b2eee97903 | |||
a4c1baa410 | |||
a4df3252f2 |
20 changed files with 518 additions and 206 deletions
|
@ -14,6 +14,10 @@ FixNamespaceComments: false
|
||||||
PackConstructorInitializers: Never
|
PackConstructorInitializers: Never
|
||||||
AlignAfterOpenBracket: AlwaysBreak
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
InsertBraces: true
|
InsertBraces: true
|
||||||
|
SpaceBeforeParens: Custom
|
||||||
|
SpaceBeforeParensOptions:
|
||||||
|
AfterControlStatements: true
|
||||||
|
AfterFunctionDefinitionName: false
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterClass: true # false
|
AfterClass: true # false
|
||||||
AfterControlStatement: false
|
AfterControlStatement: false
|
||||||
|
|
|
@ -5,6 +5,7 @@ add_library(f4ll STATIC
|
||||||
src/fault.cpp
|
src/fault.cpp
|
||||||
src/memcpy_dma.cpp
|
src/memcpy_dma.cpp
|
||||||
src/packet_usart.cpp
|
src/packet_usart.cpp
|
||||||
|
src/ringbuffer.cpp
|
||||||
src/str_util.cpp
|
src/str_util.cpp
|
||||||
src/usart_core.cpp
|
src/usart_core.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,23 +5,34 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LL_CONSOLEHANDLER_H_
|
#pragma once
|
||||||
#define LL_CONSOLEHANDLER_H_
|
|
||||||
|
|
||||||
|
#include <f4ll/initialized_singleton.h>
|
||||||
#include <f4ll/packet_usart.h>
|
#include <f4ll/packet_usart.h>
|
||||||
#include <f4ll/singleton.h>
|
#include <f4ll/ringbuffer.h>
|
||||||
|
|
||||||
namespace f4ll {
|
namespace f4ll {
|
||||||
|
|
||||||
class console_handler : public usart_core, public singleton<console_handler>
|
class console_handler : public usart_core, public initialized_singleton<console_handler>
|
||||||
{
|
{
|
||||||
friend class singleton<console_handler>;
|
friend class initialized_singleton<console_handler>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void PrintStats(uint8_t id, packet_usart &usart);
|
using size_type = iringbuffer::size_type;
|
||||||
|
class iconsole_input
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void input_available(size_type len) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void print(char const *s);
|
||||||
|
void flush();
|
||||||
|
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;
|
||||||
|
@ -35,10 +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;
|
||||||
|
|
||||||
char m_buffer[128];
|
ringbuffer_ext m_tx_buffer;
|
||||||
uint16_t m_used = 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 */
|
||||||
|
|
||||||
#endif /* LL_CONSOLEHANDLER_H_ */
|
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <f4ll/dma_helper.h>
|
#include <f4ll/dma_helper.h>
|
||||||
#include <f4ll/singleton.h>
|
#include <f4ll/initialized_singleton.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <platform/dma_ll.h>
|
#include <platform/dma_ll.h>
|
||||||
|
|
||||||
namespace f4ll {
|
namespace f4ll {
|
||||||
|
|
||||||
class crc_handler : public singleton<crc_handler>
|
class crc_handler : public initialized_singleton<crc_handler>
|
||||||
{
|
{
|
||||||
friend class singleton<crc_handler>;
|
friend class initialized_singleton<crc_handler>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct icallback
|
struct icallback
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LL_DMAHELPER_H_
|
#pragma once
|
||||||
#define LL_DMAHELPER_H_
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <platform/dma_ll.h>
|
#include <platform/dma_ll.h>
|
||||||
|
@ -56,5 +55,3 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace f4ll */
|
} /* namespace f4ll */
|
||||||
|
|
||||||
#endif /* LL_DMAHELPER_H_ */
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#ifndef __FAULT_H
|
#pragma once
|
||||||
#define __FAULT_H
|
|
||||||
|
|
||||||
#define FAULT_REASON_HARD_FAULT 1
|
#define FAULT_REASON_HARD_FAULT 1
|
||||||
#define FAULT_REASON_MEMMANAGE_FAULT 2
|
#define FAULT_REASON_MEMMANAGE_FAULT 2
|
||||||
#define FAULT_REASON_BUS_FAULT 3
|
#define FAULT_REASON_BUS_FAULT 3
|
||||||
#define FAULT_REASON_USAGE_FAULT 4
|
#define FAULT_REASON_USAGE_FAULT 4
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -43,5 +42,3 @@ __attribute__((noreturn)) void fault_handler(uint32_t type, fault_context_t *con
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __FAULT_H */
|
|
||||||
|
|
27
inc/f4ll/initialized_singleton.h
Normal file
27
inc/f4ll/initialized_singleton.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace f4ll {
|
||||||
|
|
||||||
|
template <typename T> class initialized_singleton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static T &instance() { return *m_instance; }
|
||||||
|
template <typename... args_t> static T &init(args_t &&...args)
|
||||||
|
{
|
||||||
|
static T instance{std::forward<args_t>(args)...};
|
||||||
|
m_instance = &instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
initialized_singleton() = default;
|
||||||
|
initialized_singleton(const initialized_singleton &) = delete;
|
||||||
|
initialized_singleton &operator=(const initialized_singleton &) = delete;
|
||||||
|
static T *m_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> T *initialized_singleton<T>::m_instance = nullptr;
|
||||||
|
|
||||||
|
} // namespace f1ll {
|
|
@ -1,5 +1,4 @@
|
||||||
#ifndef _IRQLOCK_H_INCLUDED
|
#pragma once
|
||||||
#define _IRQLOCK_H_INCLUDED
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stm32f4xx.h>
|
#include <stm32f4xx.h>
|
||||||
|
@ -19,8 +18,6 @@ public:
|
||||||
inline ~irq_lock() { __set_PRIMASK(m_primask); }
|
inline ~irq_lock() { __set_PRIMASK(m_primask); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t m_primask;
|
uint32_t m_primask;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _IRQLOCK_H_INCLUDED
|
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <f4ll/dma_helper.h>
|
#include <f4ll/dma_helper.h>
|
||||||
#include <f4ll/singleton.h>
|
#include <f4ll/initialized_singleton.h>
|
||||||
|
|
||||||
namespace f4ll {
|
namespace f4ll {
|
||||||
|
|
||||||
class memcpy_dma : public singleton<memcpy_dma>, private dma_helper
|
class memcpy_dma : public initialized_singleton<memcpy_dma>, private dma_helper
|
||||||
{
|
{
|
||||||
friend class singleton<memcpy_dma>;
|
friend class initialized_singleton<memcpy_dma>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void *copy(void *dst, void const *src, uint16_t length);
|
void *copy(void *dst, void const *src, uint16_t length);
|
||||||
|
@ -24,4 +24,4 @@ private:
|
||||||
bool volatile m_busy = false;
|
bool volatile m_busy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace f4ll */
|
} // namespace f4ll
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LL_HSUSART_H_
|
#pragma once
|
||||||
#define LL_HSUSART_H_
|
|
||||||
|
#include <platform/usart_ll.h>
|
||||||
|
|
||||||
#include <f4ll/crc_handler.h>
|
#include <f4ll/crc_handler.h>
|
||||||
#include <f4ll/usart_core.h>
|
#include <f4ll/usart_core.h>
|
||||||
#include <platform/usart_ll.h>
|
|
||||||
|
|
||||||
namespace f4ll {
|
namespace f4ll {
|
||||||
|
|
||||||
|
@ -119,4 +120,3 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif /* LL_HSUSART_H_ */
|
|
||||||
|
|
134
inc/f4ll/ringbuffer.h
Normal file
134
inc/f4ll/ringbuffer.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* ringbuffer.h
|
||||||
|
*
|
||||||
|
* Created on: May 31, 2025
|
||||||
|
* Author: Attila Body
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
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[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(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 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.
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
class ringbuffer_ext : public iringbuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ringbuffer_ext(uint8_t *bptr, size_type bsize);
|
||||||
|
|
||||||
|
size_type put(uint8_t const *data, size_type len) override;
|
||||||
|
void commit() override;
|
||||||
|
|
||||||
|
bool get_chunk(uint8_t const *&data, size_type &len) const 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 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; //!< Data bufer
|
||||||
|
size_type const m_bsize; //!< Data buffer size
|
||||||
|
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;
|
||||||
|
size_type max_chunk_len() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
template <iringbuffer::size_type SZ> class ringbuffer : public ringbuffer_ext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ringbuffer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_buffer[SZ];
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
template <iringbuffer::size_type SZ>
|
||||||
|
ringbuffer<SZ>::ringbuffer()
|
||||||
|
: ringbuffer_ext(m_buffer, SZ)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace f1ll
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef SINGLETON_H_
|
|
||||||
#define SINGLETON_H_
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace f4ll {
|
|
||||||
|
|
||||||
template <typename T> class singleton
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static T &instance()
|
|
||||||
{
|
|
||||||
return *m_instance;
|
|
||||||
}
|
|
||||||
template <typename... args_t> static T &init(args_t &&...args)
|
|
||||||
{
|
|
||||||
static T instance{std::forward<args_t>(args)...};
|
|
||||||
m_instance = &instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
singleton() = default;
|
|
||||||
singleton(const singleton &) = delete;
|
|
||||||
singleton &operator=(const singleton &) = delete;
|
|
||||||
static T *m_instance;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> T *singleton<T>::m_instance = nullptr;
|
|
||||||
|
|
||||||
} // namespace f1ll {
|
|
||||||
|
|
||||||
#endif /* SINGLETON_H_ */
|
|
|
@ -5,8 +5,7 @@
|
||||||
* Author: compi
|
* Author: compi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _STM32PLUS_STRUTIL_H_
|
#pragma once
|
||||||
#define _STM32PLUS_STRUTIL_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -27,5 +26,3 @@ char tochr(const uint8_t in, const uint8_t upper);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _STM32PLUS_STRUTIL_H_ */
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LL_USARTCORE_H_
|
#pragma once
|
||||||
#define LL_USARTCORE_H_
|
|
||||||
#include <platform/usart_ll.h>
|
#include <platform/usart_ll.h>
|
||||||
|
|
||||||
#include <f4ll/dma_helper.h>
|
#include <f4ll/dma_helper.h>
|
||||||
|
@ -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;
|
||||||
|
@ -44,11 +45,10 @@ private:
|
||||||
virtual void tx_dma_half_transfer(void) = 0;
|
virtual void tx_dma_half_transfer(void) = 0;
|
||||||
virtual void tx_dma_error(dma_helper::dma_error_type reason) = 0;
|
virtual void tx_dma_error(dma_helper::dma_error_type reason) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
void usart_isr();
|
void usart_isr();
|
||||||
void rx_dma_isr();
|
void rx_dma_isr();
|
||||||
void tx_dma_isr();
|
void tx_dma_isr();
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace f4ll */
|
} /* namespace f4ll */
|
||||||
|
|
||||||
#endif /* LL_USARTCORE_H_ */
|
|
||||||
|
|
|
@ -5,19 +5,50 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <f4ll/console_handler.h>
|
#include <f4ll/console_handler.h>
|
||||||
|
#include <f4ll/irq_lock.h>
|
||||||
#include <f4ll/str_util.h>
|
#include <f4ll/str_util.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
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_bytes_sent);
|
||||||
|
if (m_tx_buffer.commited()) {
|
||||||
|
uint8_t const *chunk;
|
||||||
|
m_tx_buffer.get_chunk(chunk, m_bytes_sent);
|
||||||
|
if (m_bytes_sent) {
|
||||||
|
setup_transmit(chunk, m_bytes_sent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_bytes_sent = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void console_handler::framing_error(void) {}
|
void console_handler::framing_error(void) {}
|
||||||
|
|
||||||
|
@ -45,35 +76,37 @@ void console_handler::tx_dma_error(dma_helper::dma_error_type reason)
|
||||||
(void)reason;
|
(void)reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADDINFO(b, s, u) \
|
size_t console_handler::append(char const *s)
|
||||||
b += strcpy_ex(b, s); \
|
|
||||||
b += uitodec(b, u);
|
|
||||||
|
|
||||||
void console_handler::PrintStats(uint8_t id, packet_usart &usart)
|
|
||||||
{
|
{
|
||||||
char ids[] = " : ";
|
size_t len = strlen(s);
|
||||||
char *buffer = m_buffer;
|
if (!len) {
|
||||||
packet_usart::stats const &stats(usart.get_stats());
|
return 0;
|
||||||
|
}
|
||||||
|
return len - m_tx_buffer.put(reinterpret_cast<uint8_t const *>(s), len);
|
||||||
|
}
|
||||||
|
|
||||||
ids[0] = id + '0';
|
void console_handler::flush()
|
||||||
buffer += strcpy_ex(buffer, ids);
|
{
|
||||||
ADDINFO(buffer, " s: ", stats.sent);
|
if (!m_tx_buffer.uncommited()) {
|
||||||
ADDINFO(buffer, " r: ", stats.rcvd);
|
return;
|
||||||
ADDINFO(buffer, " sk: ", stats.skiped);
|
}
|
||||||
ADDINFO(buffer, " or: ", stats.overrun);
|
m_tx_buffer.commit();
|
||||||
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);
|
if (m_bytes_sent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t const *chunk;
|
||||||
|
m_tx_buffer.get_chunk(chunk, m_bytes_sent);
|
||||||
|
if (m_bytes_sent) {
|
||||||
|
setup_transmit(chunk, m_bytes_sent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void console_handler::print(char const *s)
|
||||||
|
{
|
||||||
|
append(s);
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace f4ll */
|
} /* namespace f4ll */
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Created on: Oct 26, 2019
|
* Created on: Oct 26, 2019
|
||||||
* Author: compi
|
* Author: compi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <f4ll/crc_handler.h>
|
#include <f4ll/crc_handler.h>
|
||||||
|
|
||||||
namespace f4ll {
|
namespace f4ll {
|
||||||
|
|
180
src/fault.cpp
180
src/fault.cpp
|
@ -6,7 +6,7 @@
|
||||||
* -c "tpiu config internal <logfile_full_path> uart off <cpufreq>"
|
* -c "tpiu config internal <logfile_full_path> uart off <cpufreq>"
|
||||||
*/
|
*/
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
//#include <core_cm4.h>
|
// #include <core_cm4.h>
|
||||||
#include <f4ll/fault.h>
|
#include <f4ll/fault.h>
|
||||||
#include <f4ll/str_util.h>
|
#include <f4ll/str_util.h>
|
||||||
#include <stm32f4xx.h>
|
#include <stm32f4xx.h>
|
||||||
|
@ -24,39 +24,40 @@ void __attribute__((weak)) app_fault_callback(uint32_t reason)
|
||||||
|
|
||||||
void swo_send_str(char const *str, uint8_t len, uint8_t port)
|
void swo_send_str(char const *str, uint8_t len, uint8_t port)
|
||||||
{
|
{
|
||||||
while(len) {
|
while (len) {
|
||||||
if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && // ITM enabled
|
if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && // ITM enabled
|
||||||
((ITM->TER & (1UL << port) ) != 0UL) ) // ITM Port enabled
|
((ITM->TER & (1UL << port)) != 0UL)) // ITM Port enabled
|
||||||
{
|
{
|
||||||
// Wait until shift register is free
|
// Wait until shift register is free
|
||||||
while (ITM->PORT[port].u32 == 0UL) {
|
while (ITM->PORT[port].u32 == 0UL) {
|
||||||
__ASM volatile ("nop");
|
__ASM volatile("nop");
|
||||||
}
|
}
|
||||||
if(len >= 4) {
|
if (len >= 4) {
|
||||||
ITM->PORT[port].u32 = *(uint32_t*)(str);
|
ITM->PORT[port].u32 = *(uint32_t *)(str);
|
||||||
str += 4;
|
str += 4;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
} else if(len >= 2) {
|
} else if (len >= 2) {
|
||||||
ITM->PORT[port].u16 = *(uint16_t*)(str);
|
ITM->PORT[port].u16 = *(uint16_t *)(str);
|
||||||
str += 2;
|
str += 2;
|
||||||
len -= 2;
|
len -= 2;
|
||||||
} else {
|
} else {
|
||||||
ITM->PORT[port].u8 = *(uint8_t*)(str);
|
ITM->PORT[port].u8 = *(uint8_t *)(str);
|
||||||
++str;
|
++str;
|
||||||
--len;
|
--len;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fault_print_str(char const *fmtstr, uint32_t *values)
|
void fault_print_str(char const *fmtstr, uint32_t *values)
|
||||||
{
|
{
|
||||||
char hex_str[9]={0};
|
char hex_str[9] = {0};
|
||||||
char const *next_chunk = fmtstr;
|
char const *next_chunk = fmtstr;
|
||||||
|
|
||||||
while(*fmtstr) {
|
while (*fmtstr) {
|
||||||
if(*fmtstr == '%') {
|
if (*fmtstr == '%') {
|
||||||
swo_send_str(next_chunk, fmtstr - next_chunk, 0);
|
swo_send_str(next_chunk, fmtstr - next_chunk, 0);
|
||||||
uitohex(hex_str, *values++, 8);
|
uitohex(hex_str, *values++, 8);
|
||||||
swo_send_str(hex_str, 8, 0);
|
swo_send_str(hex_str, 8, 0);
|
||||||
|
@ -71,80 +72,71 @@ void fault_print_str(char const *fmtstr, uint32_t *values)
|
||||||
|
|
||||||
void fault_handler(uint32_t type, fault_context_t *context)
|
void fault_handler(uint32_t type, fault_context_t *context)
|
||||||
{
|
{
|
||||||
uint32_t FSR[9] = {
|
uint32_t FSR[9] = {
|
||||||
SCB->HFSR,
|
SCB->HFSR, 0xff & SCB->CFSR, (0xff00 & SCB->CFSR) >> 8, (0xffff0000 & SCB->CFSR) >> 16, SCB->DFSR, SCB->AFSR, SCB->SHCSR,
|
||||||
0xff & SCB->CFSR,
|
SCB->MMFAR, SCB->BFAR};
|
||||||
(0xff00 & SCB->CFSR) >> 8,
|
|
||||||
(0xffff0000 & SCB->CFSR) >> 16,
|
|
||||||
SCB->DFSR,
|
|
||||||
SCB->AFSR,
|
|
||||||
SCB->SHCSR,
|
|
||||||
SCB->MMFAR,
|
|
||||||
SCB->BFAR
|
|
||||||
};
|
|
||||||
|
|
||||||
while(1) {
|
while (1) {
|
||||||
fault_print_str("\n++ Fault Handler ++\n\nFaultType: ",NULL);
|
fault_print_str("\n++ Fault Handler ++\n\nFaultType: ", NULL);
|
||||||
switch( type ) {
|
switch (type) {
|
||||||
case FAULT_REASON_HARD_FAULT:
|
case FAULT_REASON_HARD_FAULT:
|
||||||
fault_print_str("HardFault",NULL);
|
fault_print_str("HardFault", NULL);
|
||||||
break;
|
break;
|
||||||
case FAULT_REASON_MEMMANAGE_FAULT:
|
case FAULT_REASON_MEMMANAGE_FAULT:
|
||||||
fault_print_str("MemManageFault",NULL);
|
fault_print_str("MemManageFault", NULL);
|
||||||
break;
|
break;
|
||||||
case FAULT_REASON_BUS_FAULT:
|
case FAULT_REASON_BUS_FAULT:
|
||||||
fault_print_str("BusFault",NULL);
|
fault_print_str("BusFault", NULL);
|
||||||
break;
|
break;
|
||||||
case FAULT_REASON_USAGE_FAULT:
|
case FAULT_REASON_USAGE_FAULT:
|
||||||
fault_print_str("UsageFault",NULL);
|
fault_print_str("UsageFault", NULL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fault_print_str("Unknown Fault",NULL);
|
fault_print_str("Unknown Fault", NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fault_print_str("\n\nContext:",NULL);
|
fault_print_str("\n\nContext:", NULL);
|
||||||
|
|
||||||
fault_print_str(
|
fault_print_str(
|
||||||
"\nR0 : %"
|
"\nR0 : %"
|
||||||
"\nR1 : %"
|
"\nR1 : %"
|
||||||
"\nR2 : %"
|
"\nR2 : %"
|
||||||
"\nR3 : %"
|
"\nR3 : %"
|
||||||
"\nR4 : %"
|
"\nR4 : %"
|
||||||
"\nR5 : %"
|
"\nR5 : %"
|
||||||
"\nR6 : %"
|
"\nR6 : %"
|
||||||
"\nR7 : %"
|
"\nR7 : %"
|
||||||
"\nR8 : %"
|
"\nR8 : %"
|
||||||
"\nR9 : %"
|
"\nR9 : %"
|
||||||
"\nR10 : %"
|
"\nR10 : %"
|
||||||
"\nR11 : %"
|
"\nR11 : %"
|
||||||
"\nR12 : %"
|
"\nR12 : %"
|
||||||
"\nSP : %"
|
"\nSP : %"
|
||||||
"\nLR : %"
|
"\nLR : %"
|
||||||
"\nPC : %"
|
"\nPC : %"
|
||||||
"\nxPSR : %"
|
"\nxPSR : %"
|
||||||
"\nPSP : %"
|
"\nPSP : %"
|
||||||
"\nMSP : %",
|
"\nMSP : %",
|
||||||
(uint32_t *)context);
|
(uint32_t *)context);
|
||||||
|
|
||||||
//Capture CPUID to get core/cpu info
|
// Capture CPUID to get core/cpu info
|
||||||
fault_print_str("\nCPUID: %",(uint32_t *)&SCB->CPUID);
|
fault_print_str("\nCPUID: %", (uint32_t *)&SCB->CPUID);
|
||||||
|
|
||||||
fault_print_str(
|
fault_print_str(
|
||||||
"\nHFSR : %"
|
"\nHFSR : %"
|
||||||
"\nMMFSR: %"
|
"\nMMFSR: %"
|
||||||
"\nBFSR : %"
|
"\nBFSR : %"
|
||||||
"\nUFSR : %"
|
"\nUFSR : %"
|
||||||
"\nDFSR : %"
|
"\nDFSR : %"
|
||||||
"\nAFSR : %"
|
"\nAFSR : %"
|
||||||
"\nSHCSR: %",
|
"\nSHCSR: %",
|
||||||
FSR);
|
FSR);
|
||||||
|
|
||||||
app_fault_callback(type);
|
app_fault_callback(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
* Author: abody
|
* Author: abody
|
||||||
*/
|
*/
|
||||||
#include <f4ll/packet_usart.h>
|
#include <f4ll/packet_usart.h>
|
||||||
#include <string.h>
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace f4ll {
|
namespace f4ll {
|
||||||
|
|
||||||
|
|
150
src/ringbuffer.cpp
Normal file
150
src/ringbuffer.cpp
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
#include <f4ll/ringbuffer.h>
|
||||||
|
|
||||||
|
namespace f4ll {
|
||||||
|
|
||||||
|
ringbuffer_ext::ringbuffer_ext(uint8_t *bptr, size_type bsize)
|
||||||
|
: m_buffer(bptr),
|
||||||
|
m_bsize(bsize)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::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 = m_bsize - 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 == m_bsize) {
|
||||||
|
m_head_shadow = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunk2) {
|
||||||
|
std::memcpy(m_buffer, data + chunk1, chunk2);
|
||||||
|
m_head_shadow += chunk2;
|
||||||
|
if (m_head_shadow == m_bsize) {
|
||||||
|
m_head_shadow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ringbuffer_ext::commit()
|
||||||
|
{
|
||||||
|
m_head = m_head_shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ringbuffer_ext::get_chunk(uint8_t const *&data, size_type &len) const
|
||||||
|
{
|
||||||
|
size_type head = m_head;
|
||||||
|
size_type tail = m_tail;
|
||||||
|
size_type chunk_size = head >= tail ? head - tail : m_bsize - tail;
|
||||||
|
|
||||||
|
if (!chunk_size) {
|
||||||
|
len = 0;
|
||||||
|
return tail != head;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = m_buffer + tail;
|
||||||
|
len = chunk_size;
|
||||||
|
|
||||||
|
tail += chunk_size;
|
||||||
|
if (tail == m_bsize) {
|
||||||
|
tail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tail != head;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ringbuffer_ext::consumed(size_type len)
|
||||||
|
{
|
||||||
|
if (!len) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_tail += len;
|
||||||
|
if (m_tail == m_bsize) {
|
||||||
|
m_tail = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return marker_diff(m_head_shadow, m_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::commited() const
|
||||||
|
{
|
||||||
|
return marker_diff(m_head, m_tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ringbuffer_ext::discard()
|
||||||
|
{
|
||||||
|
m_head_shadow = m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::size() const
|
||||||
|
{
|
||||||
|
return m_bsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::used() const
|
||||||
|
{
|
||||||
|
return marker_diff(m_head_shadow, m_tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::unused() const
|
||||||
|
{
|
||||||
|
return m_bsize - used() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iringbuffer::size_type ringbuffer_ext::marker_diff(size_type m1, size_type m2) const
|
||||||
|
{
|
||||||
|
return (m1 >= m2) ? (m1 - m2) : (m_bsize - m2 + m1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#include <f4ll/str_util.h>
|
#include <f4ll/str_util.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
size_t strcpy_ex(char *dst, char const *src)
|
size_t strcpy_ex(char *dst, char const *src)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue