Fix indentation. Update doxygen comments

This commit is contained in:
Henrik Stickann 2023-02-02 22:22:14 +01:00
parent fc4eed38d5
commit 59585b2ae5
46 changed files with 2020 additions and 1960 deletions

View File

@ -0,0 +1,12 @@
#ifndef STA_CORE_ARDUINO_NOT_IMPLEMENTED_HPP
#define STA_CORE_ARDUINO_NOT_IMPLEMENTED_HPP
/**
* @defgroup sta_core_arduino Arduino
* @ingroup sta_core_platforms
* @brief Modules implemented for the Arduino platform.
*/
#endif // STA_CORE_ARDUINO_NOT_IMPLEMENTED_HPP

View File

@ -11,20 +11,14 @@
#define STA_CORE_ASSERT_HPP #define STA_CORE_ASSERT_HPP
/** /**
* @defgroup staCore Core * @defgroup sta_core Core
* @brief STA Core library * @brief STA Core library
*/ */
/** /**
* @defgroup staCoreBuildConfig Build Config * @defgroup sta_core_platforms Platforms
* @ingroup staCore * @ingroup sta_core
* @brief Build configuration options * @brief Platform specific implementations.
*/
/**
* @defgroup staCoreAssert Assert
* @ingroup staCore
* @brief Assertion handling.
*/ */
@ -49,8 +43,21 @@
#include <cstdint> #include <cstdint>
/**
* @defgroup sta_core_assert Assert
* @ingroup sta_core
* @brief Assertion handling.
*/
namespace sta namespace sta
{ {
/**
* @ingroup sta_core_assert
* @{
*/
/** /**
* @brief Handle failed assertions. * @brief Handle failed assertions.
* *
@ -62,8 +69,6 @@ namespace sta
* @param expr Asserted expression or message * @param expr Asserted expression or message
* @param file File name * @param file File name
* @param line Line number * @param line Line number
*
* @ingroup staCoreAssert
*/ */
void assert_failed(const char * expr, const char * file, uint32_t line); void assert_failed(const char * expr, const char * file, uint32_t line);
@ -71,48 +76,38 @@ namespace sta
* @brief Stop execution. * @brief Stop execution.
* *
* Weak implementation can be overridden. * Weak implementation can be overridden.
*
* @ingroup staCoreAssert
*/ */
void assert_halt(); void assert_halt();
/** @} */
} // namespace sta } // namespace sta
/** /**
* @def STA_HALT * @ingroup sta_core_assert
* @brief Set function called after failed asserts. * @{
*
* @ingroup staCoreBuildConfig
*/ */
# ifndef STA_HALT
# define STA_HALT() sta::assert_halt()
# endif // !STA_HALT
/** /**
* @brief Assert expression. * @brief Assert expression.
* *
* @param expr Expression * @param expr Expression
*
* @ingroup staCoreAssert
*/ */
# define STA_ASSERT(expr) ( (void)( !(expr) && ( sta::assert_failed(#expr, __FILE__, __LINE__), 1 ) && ( STA_HALT(), 1 ) ) ) # define STA_ASSERT(expr) ( (void)( !(expr) && ( sta::assert_failed(#expr, __FILE__, __LINE__), 1 ) && ( sta::assert_halt(), 1 ) ) )
/** /**
* @brief Assert expression. * @brief Assert expression.
* *
* @param expr Expression * @param expr Expression
* @param msg Message shown on failure * @param msg Message shown on failure
*
* @ingroup staCoreAssert
*/ */
# define STA_ASSERT_MSG(expr, msg) ( (void)( !(expr) && ( sta::assert_failed(msg, __FILE__, __LINE__), 1 ) && ( STA_HALT(), 1 ) ) ) # define STA_ASSERT_MSG(expr, msg) ( (void)( !(expr) && ( sta::assert_failed(msg, __FILE__, __LINE__), 1 ) && ( sta::assert_halt(), 1 ) ) )
/** /**
* @brief Assert expression if condition is true. * @brief Assert expression if condition is true.
* *
* @param cond Condition * @param cond Condition
* @param expr Expression * @param expr Expression
*
* @ingroup staCoreAssert
*/ */
# define STA_ASSERT_COND(cond, expr) ( (void)( (cond) ? STA_ASSERT(expr) : 1 ) ) # define STA_ASSERT_COND(cond, expr) ( (void)( (cond) ? STA_ASSERT(expr) : 1 ) )
/** /**
@ -121,13 +116,17 @@ namespace sta
* @param cond Condition * @param cond Condition
* @param expr Expression * @param expr Expression
* @param msg Message shown on failure * @param msg Message shown on failure
*
* @ingroup staCoreAssert
*/ */
# define STA_ASSERT_COND_MSG(cond, expr, msg) ( (void)( (cond) ? STA_ASSERT_MSG(expr, msg) ) ) # define STA_ASSERT_COND_MSG(cond, expr, msg) ( (void)( (cond) ? STA_ASSERT_MSG(expr, msg) ) )
/**
* @brief Expression only evaluated when assertions are enabled.
*
* @param expr Expression
*/
# define STA_ASSERT_EXTRA(expr) expr
# define STA_ASSERT_EXTRA(expr) expr; /** @} */
#else // !STA_ASSERT_ENABLED #else // !STA_ASSERT_ENABLED

View File

@ -8,11 +8,13 @@
#ifndef STA_CORE_ATOMIC_MUTEX_HPP #ifndef STA_CORE_ATOMIC_MUTEX_HPP
#define STA_CORE_ATOMIC_MUTEX_HPP #define STA_CORE_ATOMIC_MUTEX_HPP
#include <sta/config.hpp> #include <sta/config.hpp>
#ifdef STA_STDLIB_HAS_ATOMIC #ifdef STA_STDLIB_HAS_ATOMIC
# define STA_ATOMIC_ENABLED # define STA_ATOMIC_ENABLED
#endif // STA_STDLIB_HAS_ATOMIC #endif // STA_STDLIB_HAS_ATOMIC
#if defined(STA_ATOMIC_ENABLED) || defined(DOXYGEN) #if defined(STA_ATOMIC_ENABLED) || defined(DOXYGEN)
#include <sta/mutex.hpp> #include <sta/mutex.hpp>
@ -22,20 +24,20 @@
namespace sta namespace sta
{ {
/** /**
* @brief Implementation of `Mutex` interface using `std::atomic_flag`. * @brief Implementation of `Mutex` interface using `std::atomic_flag`.
*/ */
class AtomicMutex : public Mutex class AtomicMutex : public Mutex
{ {
public: public:
AtomicMutex(); AtomicMutex();
void acquire() override; void acquire() override;
void release() override; void release() override;
private: private:
std::atomic_flag lock_; /**< Atomic flag used as lock */ std::atomic_flag lock_; /**< Atomic flag used as lock */
}; };
} // namespace sta } // namespace sta

View File

@ -8,11 +8,13 @@
#ifndef STA_CORE_ATOMIC_SIGNAL_HPP #ifndef STA_CORE_ATOMIC_SIGNAL_HPP
#define STA_CORE_ATOMIC_SIGNAL_HPP #define STA_CORE_ATOMIC_SIGNAL_HPP
#include <sta/config.hpp> #include <sta/config.hpp>
#ifdef STA_STDLIB_HAS_ATOMIC #ifdef STA_STDLIB_HAS_ATOMIC
# define STA_ATOMIC_ENABLED # define STA_ATOMIC_ENABLED
#endif // STA_STDLIB_HAS_ATOMIC #endif // STA_STDLIB_HAS_ATOMIC
#if defined(STA_ATOMIC_ENABLED) || defined(DOXYGEN) #if defined(STA_ATOMIC_ENABLED) || defined(DOXYGEN)
#include <sta/signal.hpp> #include <sta/signal.hpp>
@ -22,22 +24,22 @@
namespace sta namespace sta
{ {
/** /**
* @brief Implementation of `Signal` interface using `std::atomic`. * @brief Implementation of `Signal` interface using `std::atomic`.
*/ */
class AtomicSignal : public Signal class AtomicSignal : public Signal
{ {
public: public:
AtomicSignal(); AtomicSignal();
void notify() override; void notify() override;
bool peek() override; bool peek() override;
bool test() override; bool test() override;
void wait() override; void wait() override;
private: private:
std::atomic<bool> signal_; /**< Atomic bool used as signal */ std::atomic<bool> signal_; /**< Atomic bool used as signal */
}; };
} // namespace sta } // namespace sta

View File

@ -6,16 +6,11 @@
#define STA_CORE_CAN_CONTROLLER_HPP #define STA_CORE_CAN_CONTROLLER_HPP
/** /**
* @defgroup can CAN * @defgroup sta_core_can CAN
* @ingroup sta_core
* @brief CAN controller driver interface. * @brief CAN controller driver interface.
*/ */
/**
* @defgroup canAPI API
* @ingroup can
* @brief Public interface.
*/
#include <sta/can/filter.hpp> #include <sta/can/filter.hpp>
#include <sta/can/headers.hpp> #include <sta/can/headers.hpp>
@ -24,96 +19,96 @@
namespace sta namespace sta
{ {
/** /**
* @brief CAN controller driver interface. * @brief CAN controller driver interface.
* *
* @ingroup canAPI * @ingroup sta_core_can
*/ */
class CanController class CanController
{ {
public: public:
// RX/TX // RX/TX
// //
/** /**
* @brief Send frame to CAN controller for transmission. * @brief Send frame to CAN controller for transmission.
* *
* @param header CAN frame TX header * @param header CAN frame TX header
* @param payload CAN frame payload * @param payload CAN frame payload
* @return True on success * @return True on success
*/ */
virtual bool sendFrame(const CanTxHeader & header, const uint8_t * payload) = 0; virtual bool sendFrame(const CanTxHeader & header, const uint8_t * payload) = 0;
/** /**
* @brief Get received frame from the CAN controller. * @brief Get received frame from the CAN controller.
* *
* @param[in] fifo FIFO storing frame * @param[in] fifo FIFO storing frame
* @param[out] header CAN frame RX header destination * @param[out] header CAN frame RX header destination
* @param[out] payload CAN frame payload destination * @param[out] payload CAN frame payload destination
* @return True on success * @return True on success
*/ */
virtual bool receiveFrame(uint8_t fifo, CanRxHeader * header, uint8_t * payload) = 0; virtual bool receiveFrame(uint8_t fifo, CanRxHeader * header, uint8_t * payload) = 0;
/** /**
* @brief Get RX FIFO flags. * @brief Get RX FIFO flags.
* *
* @return FIFO flags * @return FIFO flags
*/ */
virtual uint32_t getRxFifoFlags() = 0; virtual uint32_t getRxFifoFlags() = 0;
/** /**
* @brief Get list of RX FIFO indices with pending messages. * @brief Get list of RX FIFO indices with pending messages.
*/ */
virtual CanPendingRxFifos getPendingRxFifos() = 0; virtual CanPendingRxFifos getPendingRxFifos() = 0;
// RX filter // RX filter
// //
/** /**
* @brief Change filter settings. * @brief Change filter settings.
* *
* @param idx Filter index * @param idx Filter index
* @param filter Filter configuration * @param filter Filter configuration
* @param active Enable filter after applying settings * @param active Enable filter after applying settings
*/ */
virtual void configureFilter(uint8_t idx, const CanFilter & filter, bool active = false) = 0; virtual void configureFilter(uint8_t idx, const CanFilter & filter, bool active = false) = 0;
/** /**
* @brief Enable filter. * @brief Enable filter.
* *
* @param idx Filter index * @param idx Filter index
*/ */
virtual void enableFilter(uint8_t idx) = 0; virtual void enableFilter(uint8_t idx) = 0;
/** /**
* @brief Disable filter. * @brief Disable filter.
* *
* @param idx Filter index * @param idx Filter index
*/ */
virtual void disableFilter(uint8_t idx) = 0; virtual void disableFilter(uint8_t idx) = 0;
/** /**
* @brief Disable and clear all filters. * @brief Disable and clear all filters.
*/ */
virtual void clearFilters() = 0; virtual void clearFilters() = 0;
// Info // Info
// //
/** /**
* @brief Get number of available filters. * @brief Get number of available filters.
*/ */
virtual uint8_t maxFilterCount() const = 0; virtual uint8_t maxFilterCount() const = 0;
/** /**
* @brief Get number of available FIFOs. * @brief Get number of available FIFOs.
*/ */
virtual uint8_t maxFifoCount() const = 0; virtual uint8_t maxFifoCount() const = 0;
/** /**
* @brief Get maximum supported payload size. * @brief Get maximum supported payload size.
*/ */
virtual uint8_t maxPayloadSize() const = 0; virtual uint8_t maxPayloadSize() const = 0;
}; };
} // namespace sta } // namespace sta

View File

@ -12,37 +12,37 @@
namespace sta namespace sta
{ {
/** /**
* @defgroup canFilter Filters * @defgroup sta_core_can_filters Filters
* @ingroup canAPI * @ingroup sta_core_can
* @brief CAN message filter types. * @brief CAN message filter types.
*/ * @{
*/
/** /**
* @brief ID format matched by CAN filter. * @brief ID format matched by CAN filter.
* */
* @ingroup canFilter enum class CanFilterIdFormat
*/ {
enum class CanFilterIdFormat ANY, /**< Match both ID formats */
{ STD, /**< Match standard format IDs */
ANY, /**< Match both ID formats */ EXT /**< Match extended format IDs */
STD, /**< Match standard format IDs */ };
EXT /**< Match extended format IDs */
};
/** /**
* @brief CAN filter settings. * @brief CAN filter settings.
* */
* @ingroup canFilter struct CanFilter
*/ {
struct CanFilter CanId obj; /**< ID object */
{ CanId mask; /**< ID mask */
CanId obj; /**< ID object */ CanFilterIdFormat type; /**< ID format to match */
CanId mask; /**< ID mask */ uint8_t fifo; /**< FIFO to store matches */
CanFilterIdFormat type; /**< ID format to match */ };
uint8_t fifo; /**< FIFO to store matches */
};
/** @} */
} // namespace sta } // namespace sta

View File

@ -12,36 +12,36 @@
namespace sta namespace sta
{ {
/** /**
* @defgroup canHeader Frame headers * @defgroup sta_core_can_headers Frame headers
* @ingroup canAPI * @ingroup sta_core_can
* @brief CAN header types for transmitted / received frames. * @brief CAN header types for transmitted / received frames.
*/ * @{
*/
/** /**
* @brief CAN TX frame header. * @brief CAN TX frame header.
* */
* @ingroup canHeader struct CanTxHeader
*/ {
struct CanTxHeader CanFrameId id; /**< Frame ID */
{ uint8_t payloadLength; /**< Size of data to send */
CanFrameId id; /**< Frame ID */ };
uint8_t payloadLength; /**< Size of data to send */
};
/** /**
* @brief CAN RX frame header. * @brief CAN RX frame header.
* */
* @ingroup canHeader struct CanRxHeader
*/ {
struct CanRxHeader CanFrameId id; /**< Frame ID */
{ uint8_t payloadLength; /**< Size of received data */
CanFrameId id; /**< Frame ID */ uint32_t timestamp; /**< RX timestamp */
uint8_t payloadLength; /**< Size of received data */ uint8_t filter; /**< RX filter match */
uint32_t timestamp; /**< RX timestamp */ };
uint8_t filter; /**< RX filter match */
};
/** @} */
} // namespace sta } // namespace sta

View File

@ -10,107 +10,99 @@
namespace sta namespace sta
{ {
/** /**
* @defgroup canID Frame IDs * @defgroup sta_core_can_ids Frame IDs
* @ingroup canAPI * @ingroup sta_core_can
* @brief Types for working with CAN ID values and formats. * @brief Types for working with CAN ID values and formats.
*/ */
/** /**
* @brief CAN frame ID format. * @brief CAN frame ID format.
* *
* @ingroup canID * @ingroup sta_core_can_ids
*/ */
enum class CanIdFormat : uint8_t enum class CanIdFormat : uint8_t
{ {
STD, /**< Standard format */ STD, /**< Standard format */
EXT /**< Extended format */ EXT /**< Extended format */
}; };
/** /**
* @brief CAN frame ID. * @brief CAN frame ID.
* *
* @ingroup canID * @ingroup sta_core_can_ids
*/ */
struct CanId struct CanId
{ {
uint32_t sid; /**< Standard ID field (11 bits) */ uint32_t sid; /**< Standard ID field (11 bits) */
uint32_t eid; /**< Extended ID field (18 bits) */ uint32_t eid; /**< Extended ID field (18 bits) */
}; };
/** /**
* @brief CAN frame ID and format. * @brief CAN frame ID and format.
* *
* @ingroup canID * @ingroup sta_core_can_ids
*/ */
struct CanFrameId struct CanFrameId
{ {
CanIdFormat format; /**< ID format */ CanIdFormat format; /**< ID format */
uint32_t sid; /**< Standard ID field (11 bits) */ uint32_t sid; /**< Standard ID field (11 bits) */
uint32_t eid; /**< Extended ID field (18 bits) */ uint32_t eid; /**< Extended ID field (18 bits) */
}; };
// Comparison operators // Comparison operators
// //
/** /**
* @brief Equal to operator. * @brief Equal to operator.
* *
* @param lhs Left hand side CAN ID * @param lhs Left hand side CAN ID
* @param rhs Right hand side CAN ID * @param rhs Right hand side CAN ID
* @return True if CAN IDs are equal * @return True if CAN IDs are equal
* */
* @ingroup canID bool operator ==(const CanId & lhs, const CanId & rhs);
*/ /**
bool operator ==(const CanId & lhs, const CanId & rhs); * @brief Not equal to operator.
/** *
* @brief Not equal to operator. * @param lhs Left hand side CAN ID
* * @param rhs Right hand side CAN ID
* @param lhs Left hand side CAN ID * @return True if CAN IDs are not equal
* @param rhs Right hand side CAN ID */
* @return True if CAN IDs are not equal bool operator !=(const CanId & lhs, const CanId & rhs);
*
* @ingroup canID
*/
bool operator !=(const CanId & lhs, const CanId & rhs);
/** /**
* @brief Equal to operator. * @brief Equal to operator.
* *
* @param lhs Left hand side CAN Frame ID * @param lhs Left hand side CAN Frame ID
* @param rhs Right hand side CAN Frame ID * @param rhs Right hand side CAN Frame ID
* @return True if CAN Frame IDs are equal * @return True if CAN Frame IDs are equal
* */
* @ingroup canID bool operator ==(const CanFrameId & lhs, const CanFrameId & rhs);
*/ /**
bool operator ==(const CanFrameId & lhs, const CanFrameId & rhs); * @brief Not equal to operator.
/** *
* @brief Not equal to operator. * @param lhs Left hand side CAN Frame ID
* * @param rhs Right hand side CAN Frame ID
* @param lhs Left hand side CAN Frame ID * @return True if CAN Frame IDs are not equal
* @param rhs Right hand side CAN Frame ID */
* @return True if CAN Frame IDs are not equal bool operator !=(const CanFrameId & lhs, const CanFrameId & rhs);
*
* @ingroup canID
*/
bool operator !=(const CanFrameId & lhs, const CanFrameId & rhs);
} // namespace sta } // namespace sta
/** /**
* @brief Maximum CAN standard ID value. * @brief Maximum CAN standard ID value.
* *
* @ingroup canID * @ingroup sta_core_can_ids
*/ */
#define CAN_SID_MAX UINT32_C(0x7FF) #define CAN_SID_MAX UINT32_C(0x7FF)
/** /**
* @brief Maximum CAN extended ID value. * @brief Maximum CAN extended ID value.
* *
* @ingroup canID * @ingroup sta_core_can_ids
*/ */
#define CAN_EID_MAX UINT32_C(0x3FFFF) #define CAN_EID_MAX UINT32_C(0x3FFFF)

View File

@ -10,57 +10,72 @@
namespace sta namespace sta
{ {
class CanPendingRxFifos /**
{ * @brief Iterable container interface for CAN RX flags.
public: *
using value_type = uint8_t; * @ingroup sta_core_can_ids
using reference = value_type &; */
using const_reference = const value_type &; class CanPendingRxFifos
using size_type = uint8_t; {
public:
using value_type = uint8_t;
using reference = value_type &;
using const_reference = const value_type &;
using size_type = uint8_t;
class const_iterator /**
{ * @brief Custom iterator for active RX queues.
public: */
using value_type = CanPendingRxFifos::value_type; class const_iterator
using reference = const_reference; {
using pointer = const value_type *; public:
using value_type = CanPendingRxFifos::value_type;
using reference = const_reference;
using pointer = const value_type *;
public: public:
const_iterator(const const_iterator & iter); const_iterator(const const_iterator & iter);
const_iterator & operator=(const const_iterator & iter); const_iterator & operator=(const const_iterator & iter);
bool operator==(const const_iterator & iter) const; bool operator==(const const_iterator & iter) const;
bool operator!=(const const_iterator & iter) const; bool operator!=(const const_iterator & iter) const;
const_iterator & operator++(); const_iterator & operator++();
const_iterator operator++(int); const_iterator operator++(int);
reference operator*() const; reference operator*() const;
private: private:
const_iterator(uint32_t rxFlags, uint8_t idx, uint8_t endIdx); const_iterator(uint32_t rxFlags, uint8_t idx, uint8_t endIdx);
bool isRxPending() const; /**
* @brief Check if current RX queue has pending data.
*/
bool isRxPending() const;
friend class CanPendingRxFifos; friend class CanPendingRxFifos;
private: private:
uint32_t rxFlags_; uint32_t rxFlags_; /**< RX flag bits */
uint8_t idx_; uint8_t idx_; /**< Current flag index */
uint8_t endIdx_; uint8_t endIdx_; /**< Iterator end index */
}; };
public: public:
CanPendingRxFifos(uint32_t rxFlags, uint8_t numFifos); /**
* @param rxFlags RX flag bits
* @param numFifos Number of RX FIFOs
*/
CanPendingRxFifos(uint32_t rxFlags, uint8_t numFifos);
const_iterator begin() const; const_iterator begin() const;
const_iterator end() const; const_iterator end() const;
private: private:
uint32_t rxFlags_; uint32_t rxFlags_; /**< RX flag bits */
uint8_t numFifos_; uint8_t numFifos_; /**< Number of RX FIFOs */
}; };
} // namespace sta } // namespace sta

View File

@ -11,90 +11,88 @@
namespace sta namespace sta
{ {
/** /**
* @defgroup canSub Subscription * @defgroup sta_core_can_sub Subscription
* @ingroup canAPI * @ingroup sta_core_can
* @brief Subscription interface for CAN controller drivers. * @brief Subscription interface for CAN controller drivers.
*/ * @{
*/
/** /**
* @brief Callback for handling received frames. * @brief Callback for handling received frames.
* *
* @param header Frame header * @param header Frame header
* @param buffer Frame payload buffer * @param buffer Frame payload buffer
* */
* @ingroup canSub using CanRxCallback = void (*) (const CanRxHeader & header, const uint8_t * buffer);
*/
using CanRxCallback = void (*) (const CanRxHeader & header, const uint8_t * buffer);
/** /**
* @brief Filter configuration and message handler. * @brief Filter configuration and message handler.
* */
* @ingroup canSub struct CanFilterConfig
*/ {
struct CanFilterConfig CanFilter filter; /**< Filter handled by callback */
{ CanRxCallback callback; /**< Callback for message handling */
CanFilter filter; /**< Filter handled by callback */ };
CanRxCallback callback; /**< Callback for message handling */
};
/** /**
* @brief CAN controller with subscriptions. * @brief CAN controller with subscriptions.
* *
* @tparam T Implementation of CanController interface * @tparam T Implementation of CanController interface
* */
* @ingroup canSub template <typename T>
*/ class SubscribableCanController : public T
template <typename T> {
class SubscribableCanController : public T public:
{ using T::T;
public:
using T::T;
// Subscriptions // Subscriptions
// //
/** /**
* @brief Subscribe to specific message types. * @brief Subscribe to specific message types.
* *
* @param subscriptions Array of message filters and handlers * @param subscriptions Array of message filters and handlers
* @param num Number of array entries * @param num Number of array entries
*/ */
bool subscribe(const CanFilterConfig * subscriptions, uint8_t num); bool subscribe(const CanFilterConfig * subscriptions, uint8_t num);
/** /**
* @brief Subscribe to all messages. * @brief Subscribe to all messages.
* *
* @param callback Called when message is received * @param callback Called when message is received
* @param fifo FIFO used for received messages * @param fifo FIFO used for received messages
*/ */
void subscribeAll(CanRxCallback callback, uint8_t fifo); void subscribeAll(CanRxCallback callback, uint8_t fifo);
/** /**
* @brief Unsubscribe from all messages. * @brief Unsubscribe from all messages.
* *
* No more messages will be received. * No more messages will be received.
*/ */
void unsubscribeAll(); void unsubscribeAll();
/** /**
* @brief Read message from RX FIFO and notify subscriber. * @brief Read message from RX FIFO and notify subscriber.
*/ */
void receiveAndNotify(uint8_t fifo); void receiveAndNotify(uint8_t fifo);
/** /**
* @brief Process pending frames from RX FIFOs. * @brief Process pending frames from RX FIFOs.
*/ */
void processMessages(); void processMessages();
private: private:
CanRxCallback filterCallbacks_[T::MAX_FILTER_COUNT]; /**< Callbacks for RX filters */ CanRxCallback filterCallbacks_[T::MAX_FILTER_COUNT]; /**< Callbacks for RX filters */
}; };
/** @} */
} // namespace sta } // namespace sta

View File

@ -15,105 +15,105 @@
namespace sta namespace sta
{ {
template <typename T> template <typename T>
bool SubscribableCanController<T>::subscribe(const CanFilterConfig * subscriptions, uint8_t num) bool SubscribableCanController<T>::subscribe(const CanFilterConfig * subscriptions, uint8_t num)
{ {
// Check bounds // Check bounds
if (num > T::MAX_FILTER_COUNT) if (num > T::MAX_FILTER_COUNT)
return false; return false;
// Clear previous subscriptions // Clear previous subscriptions
unsubscribeAll(); unsubscribeAll();
for (uint8_t i = 0; i < num; ++i) for (uint8_t i = 0; i < num; ++i)
{ {
// Save handler callback // Save handler callback
filterCallbacks_[i] = subscriptions[i].callback; filterCallbacks_[i] = subscriptions[i].callback;
// Configure and enable filter // Configure and enable filter
T::configureFilter(i, subscriptions[i].filter, true); T::configureFilter(i, subscriptions[i].filter, true);
} }
return true; return true;
} }
template <typename T> template <typename T>
void SubscribableCanController<T>::subscribeAll(CanRxCallback callback, uint8_t fifo) void SubscribableCanController<T>::subscribeAll(CanRxCallback callback, uint8_t fifo)
{ {
uint8_t filterIdx = 0; uint8_t filterIdx = 0;
// Clear previous subscriptions // Clear previous subscriptions
unsubscribeAll(); unsubscribeAll();
// Setup default filter // Setup default filter
CanFilter filter{}; CanFilter filter{};
filter.type = CanFilterIdFormat::ANY; filter.type = CanFilterIdFormat::ANY;
filter.fifo = fifo; filter.fifo = fifo;
// Store callback // Store callback
filterCallbacks_[filterIdx] = callback; filterCallbacks_[filterIdx] = callback;
// Configure and enable default filter // Configure and enable default filter
T::configureFilter(filterIdx, filter, true); T::configureFilter(filterIdx, filter, true);
} }
template <typename T> template <typename T>
void SubscribableCanController<T>::unsubscribeAll() void SubscribableCanController<T>::unsubscribeAll()
{ {
// Disable all filters // Disable all filters
T::clearFilters(); T::clearFilters();
// Clear filter callbacks // Clear filter callbacks
#ifndef STA_STDLIB_DISABLE #ifndef STA_STDLIB_DISABLE
std::fill_n(filterCallbacks_, T::MAX_FILTER_COUNT, nullptr); std::fill_n(filterCallbacks_, T::MAX_FILTER_COUNT, nullptr);
#else // STA_STDLIB_DISABLE #else // STA_STDLIB_DISABLE
for (uint8_t i = 0; i < T::MAX_FILTER_COUNT; ++i) for (uint8_t i = 0; i < T::MAX_FILTER_COUNT; ++i)
{ {
filterCallbacks_[i] = nullptr; filterCallbacks_[i] = nullptr;
} }
#endif // STA_STDLIB_DISABLE #endif // STA_STDLIB_DISABLE
} }
template <typename T> template <typename T>
void SubscribableCanController<T>::receiveAndNotify(uint8_t fifo) void SubscribableCanController<T>::receiveAndNotify(uint8_t fifo)
{ {
CanRxHeader header; CanRxHeader header;
uint8_t payload[T::MAX_PAYLOAD_SIZE]; uint8_t payload[T::MAX_PAYLOAD_SIZE];
if (T::receiveFrame(fifo, &header, payload)) if (T::receiveFrame(fifo, &header, payload))
{ {
//displayFrameUART(frame); //displayFrameUART(frame);
// Forward frame to filter callback // Forward frame to filter callback
if (fifo <= T::MAX_FILTER_COUNT && filterCallbacks_[header.filter]) if (fifo <= T::MAX_FILTER_COUNT && filterCallbacks_[header.filter])
{ {
filterCallbacks_[header.filter](header, payload); filterCallbacks_[header.filter](header, payload);
} }
} }
} }
template <typename T> template <typename T>
void SubscribableCanController<T>::processMessages() void SubscribableCanController<T>::processMessages()
{ {
// Read RX interrupt flags // Read RX interrupt flags
uint32_t RFIF = T::getRxFifoFlags(); uint32_t RFIF = T::getRxFifoFlags();
if (RFIF != 0) if (RFIF != 0)
{ {
// Check all flags // Check all flags
for (uint8_t fifo = 0; fifo < T::MAX_FIFO_COUNT; ++fifo) for (uint8_t fifo = 0; fifo < T::MAX_FIFO_COUNT; ++fifo)
{ {
// Process messages if flag is set // Process messages if flag is set
if (RFIF & 0x1) if (RFIF & 0x1)
{ {
receiveAndNotify(fifo); receiveAndNotify(fifo);
} }
// Shift next RX flag to LSB // Shift next RX flag to LSB
RFIF >>= 1; RFIF >>= 1;
} }
} }
} }
} // namespace sta } // namespace sta

View File

@ -11,11 +11,6 @@
#ifndef STA_CORE_DEBUG_SERIAL_HPP #ifndef STA_CORE_DEBUG_SERIAL_HPP
#define STA_CORE_DEBUG_SERIAL_HPP #define STA_CORE_DEBUG_SERIAL_HPP
/**
* @defgroup staCoreDebug Debug Serial
* @ingroup staCore
* @brief Debug serial output.
*/
#include <sta/config.hpp> #include <sta/config.hpp>
@ -35,19 +30,27 @@
# endif // !STA_DEBUG_SERIAL_FORCE # endif // !STA_DEBUG_SERIAL_FORCE
#endif // STA_DEBUG_SERIAL_UART #endif // STA_DEBUG_SERIAL_UART
#if defined(STA_DEBUG_SERIAL_ENABLED) || defined(DOXYGEN) #if defined(STA_DEBUG_SERIAL_ENABLED) || defined(DOXYGEN)
#include <sta/printable_uart.hpp> #include <sta/printable_uart.hpp>
/**
* @defgroup sta_core_debug Debug Serial
* @ingroup sta_core
* @brief Debug serial output.
*/
namespace sta namespace sta
{ {
/** /**
* @brief %UART print object for debug serial output. * @brief %UART print object for debug serial output.
* *
* @ingroup staCoreDebug * @ingroup sta_core_debug
*/ */
extern PrintableUART DebugSerial; extern PrintableUART DebugSerial;
} // namespace sta } // namespace sta
@ -56,7 +59,7 @@ namespace sta
* *
* @param ... See @ref sta::PrintableUART::print * @param ... See @ref sta::PrintableUART::print
* *
* @ingroup staCoreDebug * @ingroup sta_core_debug
*/ */
# define STA_DEBUG_PRINT(...) sta::DebugSerial.print(__VA_ARGS__) # define STA_DEBUG_PRINT(...) sta::DebugSerial.print(__VA_ARGS__)
/** /**
@ -64,7 +67,7 @@ namespace sta
* *
* @param ... See @ref sta::PrintableUART::println * @param ... See @ref sta::PrintableUART::println
* *
* @ingroup staCoreDebug * @ingroup sta_core_debug
*/ */
# define STA_DEBUG_PRINTLN(...) sta::DebugSerial.println(__VA_ARGS__) # define STA_DEBUG_PRINTLN(...) sta::DebugSerial.println(__VA_ARGS__)
#else // !STA_DEBUG_SERIAL_ENABLED #else // !STA_DEBUG_SERIAL_ENABLED

View File

@ -5,11 +5,6 @@
#ifndef STA_CORE_ENDIAN_HPP #ifndef STA_CORE_ENDIAN_HPP
#define STA_CORE_ENDIAN_HPP #define STA_CORE_ENDIAN_HPP
/**
* @defgroup staCoreEndian Endian
* @ingroup staCore
* @brief Endian handling.
*/
#include <sta/config.hpp> #include <sta/config.hpp>
@ -18,99 +13,95 @@
#endif // !STA_MCU_BIG_ENDIAN && !STA_MCU_LITTLE_ENDIAN #endif // !STA_MCU_BIG_ENDIAN && !STA_MCU_LITTLE_ENDIAN
/**
* @defgroup sta_core_endian Endian
* @ingroup sta_core
* @brief Endian handling.
* @{
*/
/** /**
* @brief Get 16-bit value with swapped byte order. * @brief Get 16-bit value with swapped byte order.
* *
* @param u16 16-bit input value * @param u16 16-bit input value
* @return 16-bit value w/ swapped byte order * @return 16-bit value w/ swapped byte order
*
* @ingroup staCoreEndian
*/ */
#define STA_UINT16_SWAP_BYTE_ORDER(u16) \ #define STA_UINT16_SWAP_BYTE_ORDER(u16) \
( \ ( \
((u16 & 0x00FF) << 8) \ ((u16 & 0x00FF) << 8) \
| ((u16 & 0xFF00) >> 8) \ | ((u16 & 0xFF00) >> 8) \
) )
/** /**
* @brief Get 32-bit value with swapped byte order. * @brief Get 32-bit value with swapped byte order.
* *
* @param u32 32-bit input value * @param u32 32-bit input value
* @return 32-bit value w/ swapped byte order * @return 32-bit value w/ swapped byte order
*
* @ingroup staCoreEndian
*/ */
#define STA_UINT32_SWAP_BYTE_ORDER(u32) \ #define STA_UINT32_SWAP_BYTE_ORDER(u32) \
( \ ( \
((u32 & 0x000000FF) << 24) \ ((u32 & 0x000000FF) << 24) \
| ((u32 & 0x0000FF00) << 8) \ | ((u32 & 0x0000FF00) << 8) \
| ((u32 & 0x00FF0000) >> 8) \ | ((u32 & 0x00FF0000) >> 8) \
| ((u32 & 0xFF000000) >> 24) \ | ((u32 & 0xFF000000) >> 24) \
) )
/** /**
* @brief Get initializer list for byte array with big-endian byte order from 16-bit value. * @brief Get initializer list for byte array with big-endian byte order from 16-bit value.
* *
* @param u16 16-bit input value * @param u16 16-bit input value
* @return Initializer list for uint8_t[2] * @return Initializer list for uint8_t[2]
*
* @ingroup staCoreEndian
*/ */
#define STA_UINT16_TO_BYTES_BE(u16) \ #define STA_UINT16_TO_BYTES_BE(u16) \
{ \ { \
static_cast<uint8_t>(u16 >> 8), \ static_cast<uint8_t>(u16 >> 8), \
static_cast<uint8_t>(u16) \ static_cast<uint8_t>(u16) \
} }
/** /**
* @brief Get initializer list for byte array with little-endian byte order from 16-bit value. * @brief Get initializer list for byte array with little-endian byte order from 16-bit value.
* *
* @param u16 16-bit input value * @param u16 16-bit input value
* @return Initializer list for uint8_t[2] * @return Initializer list for uint8_t[2]
*
* @ingroup staCoreEndian
*/ */
#define STA_UINT16_TO_BYTES_LE(u16) \ #define STA_UINT16_TO_BYTES_LE(u16) \
{ \ { \
static_cast<uint8_t>(u16), \ static_cast<uint8_t>(u16), \
static_cast<uint8_t>(u16 >> 8) \ static_cast<uint8_t>(u16 >> 8) \
} }
/** /**
* @brief Get initializer list for byte array with big-endian byte order from 32-bit value. * @brief Get initializer list for byte array with big-endian byte order from 32-bit value.
* *
* @param u32 32-bit input value * @param u32 32-bit input value
* @return Initializer list for uint8_t[4] * @return Initializer list for uint8_t[4]
*
* @ingroup staCoreEndian
*/ */
#define STA_UINT32_TO_BYTES_BE(u32) \ #define STA_UINT32_TO_BYTES_BE(u32) \
{ \ { \
static_cast<uint8_t>(u32 >> 24), \ static_cast<uint8_t>(u32 >> 24), \
static_cast<uint8_t>(u32 >> 16), \ static_cast<uint8_t>(u32 >> 16), \
static_cast<uint8_t>(u32 >> 8), \ static_cast<uint8_t>(u32 >> 8), \
static_cast<uint8_t>(u32) \ static_cast<uint8_t>(u32) \
} }
/** /**
* @brief Get initializer list for byte array with little-endian byte order from 32-bit value. * @brief Get initializer list for byte array with little-endian byte order from 32-bit value.
* *
* @param u32 32-bit input value * @param u32 32-bit input value
* @return Initializer list for uint8_t[4] * @return Initializer list for uint8_t[4]
*
* @ingroup staCoreEndian
*/ */
#define STA_UINT32_TO_BYTES_LE(u32) \ #define STA_UINT32_TO_BYTES_LE(u32) \
{ \ { \
static_cast<uint8_t>(u32), \ static_cast<uint8_t>(u32), \
static_cast<uint8_t>(u32 >> 8), \ static_cast<uint8_t>(u32 >> 8), \
static_cast<uint8_t>(u32 >> 16), \ static_cast<uint8_t>(u32 >> 16), \
static_cast<uint8_t>(u32 >> 24) \ static_cast<uint8_t>(u32 >> 24) \
} }
/** /**
* @defe STA_UINT16_TO_BE(u16) * @def STA_UINT16_TO_BE(u16)
* @brief Convert 16-bit value to big-endian byte order. * @brief Convert 16-bit value to big-endian byte order.
* *
* @param u16 16-bit input value * @param u16 16-bit input value
@ -174,6 +165,9 @@
*/ */
/** @} */
#ifdef STA_MCU_LITTLE_ENDIAN #ifdef STA_MCU_LITTLE_ENDIAN
# define STA_UINT16_TO_BE(u16) STA_UINT16_SWAP_BYTE_ORDER(u16) # define STA_UINT16_TO_BE(u16) STA_UINT16_SWAP_BYTE_ORDER(u16)
@ -186,7 +180,7 @@
# define STA_UINT32_TO_BYTES(u32) STA_UINT32_TO_BYTES_LE(u32) # define STA_UINT32_TO_BYTES(u32) STA_UINT32_TO_BYTES_LE(u32)
# define STA_UINT32_TO_BYTES_SWAP(u32) STA_UINT32_TO_BYTES_BE(u32) # define STA_UINT32_TO_BYTES_SWAP(u32) STA_UINT32_TO_BYTES_BE(u32)
#elif STA_MCU_BIG_ENDIAN #else // STA_MCU_BIG_ENDIAN
# define STA_UINT16_TO_BE(u16) (u16) # define STA_UINT16_TO_BE(u16) (u16)
# define STA_UINT16_TO_LE(u16) STA_UINT16_SWAP_BYTE_ORDER(u16) # define STA_UINT16_TO_LE(u16) STA_UINT16_SWAP_BYTE_ORDER(u16)

View File

@ -10,143 +10,143 @@
namespace sta namespace sta
{ {
/** /**
* @brief 32-bit flag register with enum type representing single flag bits. * @brief 32-bit flag register with enum type representing single flag bits.
* *
* @tparam F Enum type used for flag bits * @tparam F Enum type used for flag bits
* *
* @ingroup staCore * @ingroup sta_core
*/ */
template <typename F> template <typename F>
class EnumFlags class EnumFlags
{ {
public: public:
using flag_type = F; /**< Enum type used for flag bits */ using flag_type = F; /**< Enum type used for flag bits */
public: public:
/** /**
* @brief Default constructor. * @brief Default constructor.
*/ */
EnumFlags(); EnumFlags();
/** /**
* @brief Copy constructor. * @brief Copy constructor.
* *
* @param other Flags to copy * @param other Flags to copy
*/ */
EnumFlags(const EnumFlags & other); EnumFlags(const EnumFlags & other);
/** /**
* @brief Construct from single flag. * @brief Construct from single flag.
* *
* @param flag Single flag bit to set * @param flag Single flag bit to set
*/ */
EnumFlags(flag_type flag); EnumFlags(flag_type flag);
// Modification // Modification
// //
/** /**
* @brief Set bits from flags register. * @brief Set bits from flags register.
* *
* @param flags Flag bits to set * @param flags Flag bits to set
*/ */
void set(const EnumFlags & flags); void set(const EnumFlags & flags);
/** /**
* @brief Clear flag bits. * @brief Clear flag bits.
* *
* @param flags Flag bits to clear * @param flags Flag bits to clear
*/ */
void clear(const EnumFlags & flags); void clear(const EnumFlags & flags);
/** /**
* @brief Clear all flag bits. * @brief Clear all flag bits.
*/ */
void clear(); void clear();
// Inspection // Inspection
// //
/** /**
* @brief Test if all flags are set. * @brief Test if all flags are set.
* *
* @param flags Flag bits to check * @param flags Flag bits to check
* @return True if all checked flag bits are set * @return True if all checked flag bits are set
*/ */
bool isSet(const EnumFlags & flags) const; bool isSet(const EnumFlags & flags) const;
/** /**
* @brief Test if any flag is set. * @brief Test if any flag is set.
* *
* @param flags Flag bits to check * @param flags Flag bits to check
* @return True if any checked flag bit is set * @return True if any checked flag bit is set
*/ */
bool isAnySet(const EnumFlags & flags) const; bool isAnySet(const EnumFlags & flags) const;
// Operator overloads // Operator overloads
// //
/** /**
* @brief Equal to operator. * @brief Equal to operator.
* *
* @param rhs Flags to compare * @param rhs Flags to compare
* @return True if flags are equal * @return True if flags are equal
*/ */
bool operator ==(const EnumFlags & rhs) const; bool operator ==(const EnumFlags & rhs) const;
/** /**
* @brief Not equal to operator. * @brief Not equal to operator.
* *
* @param rhs Flags to compare * @param rhs Flags to compare
* @return True if flags are not equal * @return True if flags are not equal
*/ */
bool operator !=(const EnumFlags & rhs) const; bool operator !=(const EnumFlags & rhs) const;
/** /**
* @brief Bitwise AND operator. * @brief Bitwise AND operator.
* *
* @param rhs Other flags * @param rhs Other flags
* @return Result of bitwise AND * @return Result of bitwise AND
*/ */
EnumFlags operator &(const EnumFlags & rhs) const; EnumFlags operator &(const EnumFlags & rhs) const;
/** /**
* @brief Bitwise OR operator. * @brief Bitwise OR operator.
* *
* @param rhs Other flags * @param rhs Other flags
* @return Result of bitwise OR * @return Result of bitwise OR
*/ */
EnumFlags operator |(const EnumFlags & rhs) const; EnumFlags operator |(const EnumFlags & rhs) const;
/** /**
* @brief Bitwise AND assignment operator. * @brief Bitwise AND assignment operator.
* *
* @param rhs Other flags * @param rhs Other flags
* @return Reference to this * @return Reference to this
*/ */
EnumFlags & operator &=(const EnumFlags & rhs); EnumFlags & operator &=(const EnumFlags & rhs);
/** /**
* @brief Bitwise OR assignment operator. * @brief Bitwise OR assignment operator.
* *
* @param rhs Other flags * @param rhs Other flags
* @return Reference to this * @return Reference to this
*/ */
EnumFlags & operator |=(const EnumFlags & rhs); EnumFlags & operator |=(const EnumFlags & rhs);
/** /**
* @brief Explicitly convert flags to uint32_t. * @brief Explicitly convert flags to uint32_t.
*/ */
explicit operator uint32_t(); explicit operator uint32_t();
private: private:
/** /**
* @brief Construct from uint32_t flags. * @brief Construct from uint32_t flags.
* *
* @param flags Flags * @param flags Flags
*/ */
EnumFlags(uint32_t flags); EnumFlags(uint32_t flags);
private: private:
uint32_t flags_; /**< Flags register */ uint32_t flags_; /**< Flags register */
}; };
} // namespace sta } // namespace sta
@ -155,23 +155,23 @@ namespace sta
* *
* @param enumType Enum type to overload * @param enumType Enum type to overload
* *
* @ingroup staCore * @ingroup sta_core
*/ */
#define STA_ENUM_FLAGS_OVERLOAD(enumType) \ #define STA_ENUM_FLAGS_OVERLOAD(enumType) \
sta::EnumFlags<enumType> operator |(enumType lhs, enumType rhs) \ sta::EnumFlags<enumType> operator |(enumType lhs, enumType rhs) \
{ \ { \
return sta::EnumFlags<enumType>{lhs} | rhs; \ return sta::EnumFlags<enumType>{lhs} | rhs; \
} }
/** /**
* @brief Declare alias for sta::EnumFlags specialization. * @brief Declare alias for sta::EnumFlags specialization.
* *
* @param enumType Enum type for specialization * @param enumType Enum type for specialization
* *
* @ingroup staCore * @ingroup sta_core
*/ */
#define STA_ENUM_FLAGS_ALIAS(enumType) \ #define STA_ENUM_FLAGS_ALIAS(enumType) \
using enumType ## Flags = sta::EnumFlags<enumType> using enumType ## Flags = sta::EnumFlags<enumType>
/** /**
* @brief Declare enum and create sta::EnumFlags alias and overloads. * @brief Declare enum and create sta::EnumFlags alias and overloads.
@ -180,15 +180,15 @@ namespace sta
* @param value1 First enum value * @param value1 First enum value
* @param ... Enum values 2 - 32 * @param ... Enum values 2 - 32
* *
* @ingroup staCore * @ingroup sta_core
*/ */
#define STA_ENUM_FLAGS_DECL(enumType, value1, ...) \ #define STA_ENUM_FLAGS_DECL(enumType, value1, ...) \
enum class enumType \ enum class enumType \
{ \ { \
value1, ##__VA_ARGS__ \ value1, ##__VA_ARGS__ \
}; \ }; \
STA_ENUM_FLAGS_ALIAS(enumType); \ STA_ENUM_FLAGS_ALIAS(enumType); \
STA_ENUM_FLAGS_OVERLOAD(enumType) STA_ENUM_FLAGS_OVERLOAD(enumType)
// Include template implementation // Include template implementation

View File

@ -11,105 +11,105 @@
namespace sta namespace sta
{ {
template <typename F> template <typename F>
EnumFlags<F>::EnumFlags() EnumFlags<F>::EnumFlags()
: flags_{0} : flags_{0}
{} {}
template <typename F> template <typename F>
EnumFlags<F>::EnumFlags(const EnumFlags & other) EnumFlags<F>::EnumFlags(const EnumFlags & other)
: flags_{other.flags_} : flags_{other.flags_}
{} {}
template <typename F> template <typename F>
EnumFlags<F>::EnumFlags(flag_type flag) EnumFlags<F>::EnumFlags(flag_type flag)
: flags_{1U << static_cast<uint8_t>(flag)} : flags_{1U << static_cast<uint8_t>(flag)}
{} {}
template <typename F> template <typename F>
EnumFlags<F>::EnumFlags(uint32_t flags) EnumFlags<F>::EnumFlags(uint32_t flags)
: flags_{flags} : flags_{flags}
{} {}
template <typename F> template <typename F>
void EnumFlags<F>::set(const EnumFlags & flags) void EnumFlags<F>::set(const EnumFlags & flags)
{ {
flags_ |= flags.flags_; flags_ |= flags.flags_;
} }
template <typename F> template <typename F>
void EnumFlags<F>::clear(const EnumFlags & flags) void EnumFlags<F>::clear(const EnumFlags & flags)
{ {
flags_ &= ~(flags.flags_); flags_ &= ~(flags.flags_);
} }
template <typename F> template <typename F>
void EnumFlags<F>::clear() void EnumFlags<F>::clear()
{ {
flags_ = 0; flags_ = 0;
} }
template <typename F> template <typename F>
bool EnumFlags<F>::isSet(const EnumFlags & flags) const bool EnumFlags<F>::isSet(const EnumFlags & flags) const
{ {
return (flags_ & flags.flags_) == flags.flags_; return (flags_ & flags.flags_) == flags.flags_;
} }
template <typename F> template <typename F>
bool EnumFlags<F>::isAnySet(const EnumFlags & flags) const bool EnumFlags<F>::isAnySet(const EnumFlags & flags) const
{ {
return (flags_ & flags.flags_) != 0; return (flags_ & flags.flags_) != 0;
} }
template <typename F> template <typename F>
bool EnumFlags<F>::operator ==(const EnumFlags<F> & rhs) const bool EnumFlags<F>::operator ==(const EnumFlags<F> & rhs) const
{ {
return (flags_ == rhs.flags_); return (flags_ == rhs.flags_);
} }
template <typename F> template <typename F>
bool EnumFlags<F>::operator !=(const EnumFlags<F> & rhs) const bool EnumFlags<F>::operator !=(const EnumFlags<F> & rhs) const
{ {
return (flags_ != rhs.flags_); return (flags_ != rhs.flags_);
} }
template <typename F> template <typename F>
EnumFlags<F> EnumFlags<F>::operator &(const EnumFlags<F> & rhs) const EnumFlags<F> EnumFlags<F>::operator &(const EnumFlags<F> & rhs) const
{ {
return EnumFlags(flags_ & rhs.flags_); return EnumFlags(flags_ & rhs.flags_);
} }
template <typename F> template <typename F>
EnumFlags<F> EnumFlags<F>::operator |(const EnumFlags<F> & rhs) const EnumFlags<F> EnumFlags<F>::operator |(const EnumFlags<F> & rhs) const
{ {
return EnumFlags(flags_ | rhs.flags_); return EnumFlags(flags_ | rhs.flags_);
} }
template <typename F> template <typename F>
EnumFlags<F> & EnumFlags<F>::operator &=(const EnumFlags<F> & rhs) EnumFlags<F> & EnumFlags<F>::operator &=(const EnumFlags<F> & rhs)
{ {
flags_ &= rhs.flags_; flags_ &= rhs.flags_;
return *this; return *this;
} }
template <typename F> template <typename F>
EnumFlags<F> & EnumFlags<F>::operator |=(const EnumFlags<F> & rhs) EnumFlags<F> & EnumFlags<F>::operator |=(const EnumFlags<F> & rhs)
{ {
flags_ |= rhs.flags_; flags_ |= rhs.flags_;
return *this; return *this;
} }
template <typename F> template <typename F>
EnumFlags<F>::operator uint32_t() EnumFlags<F>::operator uint32_t()
{ {
return flags_; return flags_;
} }
} // namespace sta } // namespace sta

View File

@ -8,107 +8,107 @@
namespace sta namespace sta
{ {
/** /**
* @brief FIFO buffer. * @brief FIFO buffer.
* *
* @tparam Size Size type * @tparam Size Size type
* @tparam N Buffer size * @tparam N Buffer size
* *
* @ingroup staCore * @ingroup sta_core
*/ */
template <typename Size, Size N> template <typename Size, Size N>
class FifoBuffer class FifoBuffer
{ {
public: public:
/** /**
* @brief FIFO size type. * @brief FIFO size type.
*/ */
using size_type = Size; using size_type = Size;
/** /**
* @brief Max number of bytes in FIFO. * @brief Max number of bytes in FIFO.
*/ */
static constexpr size_type MAX_SIZE = N; static constexpr size_type MAX_SIZE = N;
public: public:
/** /**
* @brief Construct empty FIFO buffer. * @brief Construct empty FIFO buffer.
*/ */
FifoBuffer(); FifoBuffer();
/** /**
* @brief Construct FIFO buffer with initial data. * @brief Construct FIFO buffer with initial data.
* *
* @param buffer Source buffer * @param buffer Source buffer
* @param size Buffer size * @param size Buffer size
*/ */
FifoBuffer(const uint8_t * buffer, Size size); FifoBuffer(const uint8_t * buffer, Size size);
/** /**
* @brief Clear buffer content. * @brief Clear buffer content.
*/ */
void clear(); void clear();
/** /**
* @brief Set data in buffer. * @brief Set data in buffer.
* *
* @param buffer Source buffer * @param buffer Source buffer
* @param size Number of bytes to write * @param size Number of bytes to write
*/ */
void set(const uint8_t * buffer, size_type size); void set(const uint8_t * buffer, size_type size);
/** /**
* @brief Append value to end of buffer. * @brief Append value to end of buffer.
* *
* @param value Value * @param value Value
*/ */
void pushBack(uint8_t value); void pushBack(uint8_t value);
/** /**
* @brief Append data to end of buffer. * @brief Append data to end of buffer.
* *
* @param buffer Source buffer * @param buffer Source buffer
* @param size Number of bytes to write * @param size Number of bytes to write
*/ */
void pushBack(const uint8_t * buffer, size_type size); void pushBack(const uint8_t * buffer, size_type size);
/** /**
* @brief Append value repeatedly to end of buffer. * @brief Append value repeatedly to end of buffer.
* *
* @param value Fill value * @param value Fill value
* @param count Repeat count * @param count Repeat count
*/ */
void pushBack(uint8_t value, size_type count); void pushBack(uint8_t value, size_type count);
/** /**
* @brief Take data from start of buffer. * @brief Take data from start of buffer.
* *
* @param buffer Destination buffer * @param buffer Destination buffer
* @param size Number of bytes to read * @param size Number of bytes to read
*/ */
void popFront(uint8_t * buffer, size_type size); void popFront(uint8_t * buffer, size_type size);
/** /**
* @brief Get size of data in buffer. * @brief Get size of data in buffer.
* *
* @return Data size * @return Data size
*/ */
size_type size() const; size_type size() const;
/** /**
* @brief Check if buffer is full. * @brief Check if buffer is full.
* *
* @return True if buffer is full * @return True if buffer is full
*/ */
bool isFull() const; bool isFull() const;
/** /**
* @brief Check if buffer is empty. * @brief Check if buffer is empty.
* *
* @return True if buffer is empty * @return True if buffer is empty
*/ */
bool isEmpty() const; bool isEmpty() const;
private: private:
uint8_t * head_; /**< Read position */ uint8_t * head_; /**< Read position */
uint8_t * tail_; /**< Write position */ uint8_t * tail_; /**< Write position */
uint8_t buffer_[N]; /**< Buffer data */ uint8_t buffer_[N]; /**< Buffer data */
}; };
} // namespace sta } // namespace sta

View File

@ -10,93 +10,93 @@
namespace sta namespace sta
{ {
template <typename Size, Size N> template <typename Size, Size N>
FifoBuffer<Size, N>::FifoBuffer() FifoBuffer<Size, N>::FifoBuffer()
: head_{buffer_}, tail_{buffer_} : head_{buffer_}, tail_{buffer_}
{} {}
template <typename Size, Size N> template <typename Size, Size N>
FifoBuffer<Size, N>::FifoBuffer(const uint8_t * buffer, size_type size) FifoBuffer<Size, N>::FifoBuffer(const uint8_t * buffer, size_type size)
{ {
set(buffer, size); set(buffer, size);
} }
template <typename Size, Size N> template <typename Size, Size N>
void FifoBuffer<Size, N>::set(const uint8_t * buffer, size_type bsize) void FifoBuffer<Size, N>::set(const uint8_t * buffer, size_type bsize)
{ {
STA_ASSERT(bsize <= sizeof(buffer_)); STA_ASSERT(bsize <= sizeof(buffer_));
STA_ASSERT(buffer != nullptr); STA_ASSERT(buffer != nullptr);
head_ = buffer_; head_ = buffer_;
tail_ = buffer_ + bsize; tail_ = buffer_ + bsize;
memcpy(buffer_, buffer, bsize); memcpy(buffer_, buffer, bsize);
} }
template <typename Size, Size N> template <typename Size, Size N>
void FifoBuffer<Size, N>::clear() void FifoBuffer<Size, N>::clear()
{ {
head_ = tail_ = buffer_; head_ = tail_ = buffer_;
} }
template <typename Size, Size N> template <typename Size, Size N>
void FifoBuffer<Size, N>::pushBack(uint8_t value) void FifoBuffer<Size, N>::pushBack(uint8_t value)
{ {
STA_ASSERT_MSG(tail_ < buffer_ + sizeof(buffer_), "Buffer overflow"); STA_ASSERT_MSG(tail_ < buffer_ + sizeof(buffer_), "Buffer overflow");
*tail_++ = value; *tail_++ = value;
} }
template <typename Size, Size N> template <typename Size, Size N>
void FifoBuffer<Size, N>::pushBack(const uint8_t * buffer, size_type bsize) void FifoBuffer<Size, N>::pushBack(const uint8_t * buffer, size_type bsize)
{ {
STA_ASSERT_MSG(size() + bsize <= sizeof(buffer_), "Buffer overflow"); STA_ASSERT_MSG(size() + bsize <= sizeof(buffer_), "Buffer overflow");
STA_ASSERT(buffer != nullptr); STA_ASSERT(buffer != nullptr);
memcpy(tail_, buffer, bsize); memcpy(tail_, buffer, bsize);
tail_ += bsize; tail_ += bsize;
} }
template <typename Size, Size N> template <typename Size, Size N>
void FifoBuffer<Size, N>::pushBack(uint8_t value, size_type count) void FifoBuffer<Size, N>::pushBack(uint8_t value, size_type count)
{ {
STA_ASSERT_MSG(size() + count <= sizeof(buffer_), "Buffer overflow"); STA_ASSERT_MSG(size() + count <= sizeof(buffer_), "Buffer overflow");
memset(tail_, value, count); memset(tail_, value, count);
tail_ += count; tail_ += count;
} }
template <typename Size, Size N> template <typename Size, Size N>
void FifoBuffer<Size, N>::popFront(uint8_t * buffer, size_type bsize) void FifoBuffer<Size, N>::popFront(uint8_t * buffer, size_type bsize)
{ {
STA_ASSERT_MSG(size() >= bsize, "Not enough data"); STA_ASSERT_MSG(size() >= bsize, "Not enough data");
STA_ASSERT(buffer != nullptr); STA_ASSERT(buffer != nullptr);
memcpy(buffer, head_, bsize); memcpy(buffer, head_, bsize);
head_ += bsize; head_ += bsize;
} }
template <typename Size, Size N> template <typename Size, Size N>
typename FifoBuffer<Size, N>::size_type FifoBuffer<Size, N>::size() const typename FifoBuffer<Size, N>::size_type FifoBuffer<Size, N>::size() const
{ {
return (tail_ - head_); return (tail_ - head_);
} }
template <typename Size, Size N> template <typename Size, Size N>
bool FifoBuffer<Size, N>::isFull() const bool FifoBuffer<Size, N>::isFull() const
{ {
return (tail_ == buffer_ + sizeof(buffer_)); return (tail_ == buffer_ + sizeof(buffer_));
} }
template <typename Size, Size N> template <typename Size, Size N>
bool FifoBuffer<Size, N>::isEmpty() const bool FifoBuffer<Size, N>::isEmpty() const
{ {
return (head_ == tail_); return (head_ == tail_);
} }
} // namespace sta } // namespace sta

View File

@ -8,28 +8,39 @@
namespace sta namespace sta
{ {
/** /**
* @brief GPIO pin state. * @defgroup sta_core_gpio GPIO
*/ * @ingroup sta_core
enum class GpioPinState * @brief GPIO pins.
{ * @{
LOW, */
HIGH
};
/**
* @brief Interface for GPIO pins. /**
*/ * @brief GPIO pin state.
class GpioPin */
{ enum class GpioPinState
public: {
/** LOW,
* @brief Set pin output state. HIGH
* };
* @param state Output state
*/ /**
virtual void setState(GpioPinState state) = 0; * @brief Interface for GPIO pins.
}; */
class GpioPin
{
public:
/**
* @brief Set pin output state.
*
* @param state Output state
*/
virtual void setState(GpioPinState state) = 0;
};
/** @} */
} // namespace sta } // namespace sta

View File

@ -5,9 +5,10 @@
#ifndef STA_CORE_LANG_HPP #ifndef STA_CORE_LANG_HPP
#define STA_CORE_LANG_HPP #define STA_CORE_LANG_HPP
/** /**
* @defgroup staCoreLang Lang * @defgroup sta_core_lang Lang
* @ingroup staCore * @ingroup sta_core
* @brief Compiler instructions. * @brief Compiler instructions.
* @{ * @{
*/ */

View File

@ -8,23 +8,25 @@
namespace sta namespace sta
{ {
/** /**
* @brief Interface for mutex objects. * @brief Interface for mutex objects.
*/ *
class Mutex * @ingroup sta_core
{ */
public: class Mutex
/** {
* @brief Block until mutex has been acquired. public:
*/ /**
virtual void acquire() = 0; * @brief Block until mutex has been acquired.
/** */
* @brief Release mutex. virtual void acquire() = 0;
*/ /**
virtual void release() = 0; * @brief Release mutex.
*/
virtual void release() = 0;
static Mutex * ALWAYS_FREE; /**< Fake mutex that can always be acquired */ static Mutex * ALWAYS_FREE; /**< Fake mutex that can always be acquired */
}; };
} // namespace sta } // namespace sta

View File

@ -13,191 +13,191 @@
namespace sta namespace sta
{ {
/** /**
* @brief Integer representation. * @brief Integer representation.
* *
* @ingroup staCore * @ingroup sta_core
*/ */
enum class IntegerBase enum class IntegerBase
{ {
DEC, /**< Decimal */ DEC, /**< Decimal */
BIN, /**< Binary */ BIN, /**< Binary */
HEX /**< Hexadecimal */ HEX /**< Hexadecimal */
}; };
/** /**
* @brief Printable interface for UART. * @brief Printable interface for UART.
* *
* @ingroup staCore * @ingroup sta_core
*/ */
class PrintableUART class PrintableUART
{ {
public: public:
/** /**
* @param intf UART instance * @param intf UART instance
*/ */
PrintableUART(UART * intf); PrintableUART(UART * intf);
/** /**
* @brief Print single character. * @brief Print single character.
* *
* @param c Character to print * @param c Character to print
*/ */
void print(char c); void print(char c);
/** /**
* @brief Print boolean value. * @brief Print boolean value.
* *
* @param b Boolean value * @param b Boolean value
*/ */
void print(bool b); void print(bool b);
/** /**
* @brief Print floating point value. * @brief Print floating point value.
* *
* @param d Floating point value * @param d Floating point value
*/ */
void print(double d); void print(double d);
/** /**
* @brief Print integer in selected base. * @brief Print integer in selected base.
* *
* @param num 8-bit unsigned integer * @param num 8-bit unsigned integer
* @param base Integer base * @param base Integer base
*/ */
void print(uint8_t num, IntegerBase base = IntegerBase::DEC); void print(uint8_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print integer in selected base. * @brief Print integer in selected base.
* *
* @param num 16-bit unsigned integer * @param num 16-bit unsigned integer
* @param base Integer base * @param base Integer base
*/ */
void print(uint16_t num, IntegerBase base = IntegerBase::DEC); void print(uint16_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print integer in selected base. * @brief Print integer in selected base.
* *
* @param num 32-bit unsigned integer * @param num 32-bit unsigned integer
* @param base Integer base * @param base Integer base
*/ */
void print(uint32_t num, IntegerBase base = IntegerBase::DEC); void print(uint32_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print integer in selected base. * @brief Print integer in selected base.
* *
* @param num Integer * @param num Integer
* @param base Integer base * @param base Integer base
*/ */
void print(size_t num, IntegerBase base = IntegerBase::DEC); void print(size_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print c-string. * @brief Print c-string.
* *
* @param str Null terminated string * @param str Null terminated string
*/ */
void print(const char * str); void print(const char * str);
/** /**
* @brief Print string. * @brief Print string.
* *
* @param str String buffer * @param str String buffer
* @param length String length * @param length String length
*/ */
void print(const char * str, size_t length); void print(const char * str, size_t length);
/** /**
* @brief Print new-line. * @brief Print new-line.
*/ */
void println(); void println();
/** /**
* @brief Print single character followed by a new-line. * @brief Print single character followed by a new-line.
* *
* @param c Character to print * @param c Character to print
*/ */
void println(char c); void println(char c);
/** /**
* @brief Print boolean value followed by a new-line. * @brief Print boolean value followed by a new-line.
* *
* @param b Boolean value * @param b Boolean value
*/ */
void println(bool b); void println(bool b);
/** /**
* @brief Print floating point value followed by a new-line. * @brief Print floating point value followed by a new-line.
* *
* @param d Floating point value * @param d Floating point value
*/ */
void println(double d); void println(double d);
/** /**
* @brief Print integer in selected base followed by a new-line. * @brief Print integer in selected base followed by a new-line.
* *
* @param num 8-bit unsigned integer * @param num 8-bit unsigned integer
* @param base Integer base * @param base Integer base
*/ */
void println(uint8_t num, IntegerBase base = IntegerBase::DEC); void println(uint8_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print integer in selected base followed by a new-line. * @brief Print integer in selected base followed by a new-line.
* *
* @param num 16-bit unsigned integer * @param num 16-bit unsigned integer
* @param base Integer base * @param base Integer base
*/ */
void println(uint16_t num, IntegerBase base = IntegerBase::DEC); void println(uint16_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print integer in selected base followed by a new-line. * @brief Print integer in selected base followed by a new-line.
* *
* @param num 32-bit unsigned integer * @param num 32-bit unsigned integer
* @param base Integer base * @param base Integer base
*/ */
void println(uint32_t num, IntegerBase base = IntegerBase::DEC); void println(uint32_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print integer in selected base followed by a new-line. * @brief Print integer in selected base followed by a new-line.
* *
* @param num Integer * @param num Integer
* @param base Integer base * @param base Integer base
*/ */
void println(size_t num, IntegerBase base = IntegerBase::DEC); void println(size_t num, IntegerBase base = IntegerBase::DEC);
/** /**
* @brief Print c-string followed by a new-line. * @brief Print c-string followed by a new-line.
* *
* @param str Null terminated string * @param str Null terminated string
*/ */
void println(const char * str); void println(const char * str);
/** /**
* @brief Print string followed by a new-line. * @brief Print string followed by a new-line.
* *
* @param str String buffer * @param str String buffer
* @param length String length * @param length String length
*/ */
void println(const char * str, size_t length); void println(const char * str, size_t length);
private: private:
/** /**
* @brief Print unsigned integer in selected base. * @brief Print unsigned integer in selected base.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
* @param base Integer base * @param base Integer base
* @param fmt printf format string for base 10 * @param fmt printf format string for base 10
* @param size Size of value in bytes * @param size Size of value in bytes
*/ */
void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size); void printBase(uintmax_t value, IntegerBase base, const char * fmt, size_t size);
/** /**
* @brief Print unsigned integer in base 10. * @brief Print unsigned integer in base 10.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
* @param fmt printf format string * @param fmt printf format string
*/ */
void printDec(uintmax_t value, const char * fmt); void printDec(uintmax_t value, const char * fmt);
/** /**
* @brief Print unsigned integer in base 2. * @brief Print unsigned integer in base 2.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
* @param digits Number of digits to print * @param digits Number of digits to print
*/ */
void printBin(uintmax_t value, size_t digits); void printBin(uintmax_t value, size_t digits);
/** /**
* @brief Print unsigned integer in base 16. * @brief Print unsigned integer in base 16.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
* @param digits Number of digits to print * @param digits Number of digits to print
*/ */
void printHex(uintmax_t value, size_t digits); void printHex(uintmax_t value, size_t digits);
private: private:
UART * intf_; UART * intf_;
}; };
} // namespace sta } // namespace sta

View File

@ -8,33 +8,35 @@
namespace sta namespace sta
{ {
/** /**
* @brief Interface for signal objects. * @brief Interface for signal objects.
*/ *
class Signal * @ingroup sta_core
{ */
public: class Signal
/** {
* @brief Enter signaled state. public:
*/ /**
virtual void notify() = 0; * @brief Enter signaled state.
/** */
* @brief Check signal state w/o changing it. virtual void notify() = 0;
* /**
* @return True if in signaled state * @brief Check signal state w/o changing it.
*/ *
virtual bool peek() = 0; * @return True if in signaled state
/** */
* @brief Check signal state. virtual bool peek() = 0;
* /**
* @return True if in signaled state * @brief Check signal state.
*/ *
virtual bool test() = 0; * @return True if in signaled state
/** */
* @brief Wait until signaled state is entered. virtual bool test() = 0;
*/ /**
virtual void wait() = 0; * @brief Wait until signaled state is entered.
}; */
virtual void wait() = 0;
};
} // namespace sta } // namespace sta

View File

@ -9,8 +9,8 @@
#define STA_CORE_STM32_CAN_HPP #define STA_CORE_STM32_CAN_HPP
/** /**
* @defgroup stm32CAN CAN * @defgroup sta_core_stm32_can CAN
* @ingroup stm32 * @ingroup sta_core_stm32
* @brief STM32 CAN module. * @brief STM32 CAN module.
* *
* Check @ref stm32BuildConfig for configuration options. * Check @ref stm32BuildConfig for configuration options.
@ -33,84 +33,84 @@
namespace sta namespace sta
{ {
/** /**
* @brief Implementation of CanController interface using HAL. * @brief Implementation of CanController interface using HAL.
* *
* @ingroup stm32CAN * @ingroup sta_core_stm32_can
*/ */
class STM32CanController : public CanController class STM32CanController : public CanController
{ {
public: public:
static constexpr uint8_t MAX_FILTER_COUNT = 14; /**< Max number of filters */ static constexpr uint8_t MAX_FILTER_COUNT = 14; /**< Max number of filters */
static constexpr uint8_t MAX_FIFO_COUNT = 2; /**< Max number of FIFOs */ static constexpr uint8_t MAX_FIFO_COUNT = 2; /**< Max number of FIFOs */
static constexpr uint8_t MAX_PAYLOAD_SIZE = 8; /**< Maximum payload size */ static constexpr uint8_t MAX_PAYLOAD_SIZE = 8; /**< Maximum payload size */
public: public:
/** /**
* @param handle CAN handle * @param handle CAN handle
*/ */
STM32CanController(CAN_HandleTypeDef * handle); STM32CanController(CAN_HandleTypeDef * handle);
/** /**
* @brief Enable RX pending interrupts. * @brief Enable RX pending interrupts.
*/ */
void enableRxInterrupts(); void enableRxInterrupts();
/** /**
* @brief Start CAN controller. * @brief Start CAN controller.
*/ */
void start(); void start();
/** /**
* @brief Stop CAN controller. * @brief Stop CAN controller.
*/ */
void stop(); void stop();
// RX/TX // RX/TX
// //
bool sendFrame(const CanTxHeader & header, const uint8_t * payload) override; bool sendFrame(const CanTxHeader & header, const uint8_t * payload) override;
bool receiveFrame(uint8_t fifo, CanRxHeader * header, uint8_t * payload) override; bool receiveFrame(uint8_t fifo, CanRxHeader * header, uint8_t * payload) override;
uint32_t getRxFifoFlags() override; uint32_t getRxFifoFlags() override;
// RX Filter // RX Filter
// //
void configureFilter(uint8_t idx, const CanFilter & filter, bool active = false) override; void configureFilter(uint8_t idx, const CanFilter & filter, bool active = false) override;
void enableFilter(uint8_t idx) override; void enableFilter(uint8_t idx) override;
void disableFilter(uint8_t idx) override; void disableFilter(uint8_t idx) override;
void clearFilters() override; void clearFilters() override;
private: private:
/** /**
* @brief Initialize filter settings. * @brief Initialize filter settings.
*/ */
void initFilters(); void initFilters();
private: private:
CAN_HandleTypeDef * handle_; /**< CAN handle */ CAN_HandleTypeDef * handle_; /**< CAN handle */
CAN_FilterTypeDef filters_[MAX_FILTER_COUNT]; /**< Filter settings */ CAN_FilterTypeDef filters_[MAX_FILTER_COUNT]; /**< Filter settings */
}; };
#if defined(STA_STM32_CAN_GLOBAL) || DOXYGEN #if defined(STA_STM32_CAN_GLOBAL) || DOXYGEN
/** /**
* @brief Global CAN instance. * @brief Global CAN instance.
* *
* @ingroup stm32CAN * @ingroup sta_core_stm32_can
*/ */
extern STM32CanController CanBus; extern STM32CanController CanBus;
/** /**
* @brief Interrupt handler for pending RX frames. * @brief Interrupt handler for pending RX frames.
* *
* May be implemented by application. * May be implemented by application.
* *
* @ingroup stm32CAN * @ingroup sta_core_stm32_can
*/ */
void CanBus_RxPendingCallback(); void CanBus_RxPendingCallback();
#endif // STA_STM32_CAN_GLOBAL #endif // STA_STM32_CAN_GLOBAL
} // namespace sta } // namespace sta

View File

@ -5,30 +5,33 @@
#ifndef STA_CORE_STM32_CLOCKS_HPP #ifndef STA_CORE_STM32_CLOCKS_HPP
#define STA_CORE_STM32_CLOCKS_HPP #define STA_CORE_STM32_CLOCKS_HPP
/**
* @defgroup stm32 STM32 // Only enable module on STM32 platform
* @brief Modules implemented for STM32 MCUs. #include <sta/config.hpp>
*/
#if defined(STA_PLATFORM_STM32) || defined(DOXYGEN)
#include <sta/stm32/hal.hpp>
/** /**
* @defgroup stm32BuildConfig Build config * @defgroup sta_core_stm32_clocks Clocks
* @ingroup stm32 * @ingroup sta_core_stm32
* @brief Build configuration options.
*/
/**
* @defgroup stm32Clocks Clocks
* @ingroup stm32
* @brief STM32 Clock queries. * @brief STM32 Clock queries.
* @{ * @{
*/ */
// Only enable module on STM32 platform namespace sta
#include <sta/config.hpp> {
#if defined(STA_PLATFORM_STM32) || defined(DOXYGEN) /**
* @brief Get peripheral clock frequency.
#include <sta/stm32/hal.hpp> *
* @return Clock frequency
*/
using PCLKFreqFn = uint32_t (*)();
} // namespace sta
/** /**

View File

@ -11,14 +11,11 @@
#ifndef STA_CORE_STM32_DELAY_HPP #ifndef STA_CORE_STM32_DELAY_HPP
#define STA_CORE_STM32_DELAY_HPP #define STA_CORE_STM32_DELAY_HPP
/**
* @defgroup stm32Delay Delay
* @ingroup stm32
* @brief STM32 Delay module.
*/
// Only enable module on STM32 platform // Only enable module on STM32 platform
#include <sta/config.hpp> #include <sta/config.hpp>
#if defined(STA_PLATFORM_STM32) || defined(DOXYGEN) #if defined(STA_PLATFORM_STM32) || defined(DOXYGEN)
#include <cstdint> #include <cstdint>
@ -26,25 +23,32 @@
namespace sta namespace sta
{ {
/** /**
* @brief Millisecond delay. * @defgroup sta_core_stm32_delay Delay
* * @ingroup sta_core_stm32
* @param ms Milliseconds * @brief STM32 Delay module.
* * @{
* @ingroup stm32Delay */
*/
void delayMs(uint32_t ms);
/**
* @brief Millisecond delay.
*
* @param ms Milliseconds
*/
void delayMs(uint32_t ms);
#if defined(STA_STM32_DELAY_US_TIM) || defined(DOXYGEN) #if defined(STA_STM32_DELAY_US_TIM) || defined(DOXYGEN)
/** /**
* @brief Microsecond delay. * @brief Microsecond delay.
* *
* @param us Microseconds * @param us Microseconds
* */
* @ingroup stm32Delay void delayUs(uint32_t us);
*/
void delayUs(uint32_t us);
#endif // STA_STM32_DELAY_US_TIM #endif // STA_STM32_DELAY_US_TIM
/** @} */
} // namespace sta } // namespace sta

View File

@ -5,11 +5,6 @@
#ifndef STA_CORE_STM32_GPIO_PIN_HPP #ifndef STA_CORE_STM32_GPIO_PIN_HPP
#define STA_CORE_STM32_GPIO_PIN_HPP #define STA_CORE_STM32_GPIO_PIN_HPP
/**
* @defgroup stm32GPIO GPIO
* @ingroup stm32
* @brief STM32 GPIO module.
*/
// Only enable module on STM32 platform w/ HAL GPIO module enabled // Only enable module on STM32 platform w/ HAL GPIO module enabled
#include <sta/config.hpp> #include <sta/config.hpp>
@ -26,68 +21,81 @@
#include <sta/gpio_pin.hpp> #include <sta/gpio_pin.hpp>
/**
* @defgroup sta_core_stm32_gpio GPIO
* @ingroup sta_core_stm32
* @brief STM32 GPIO module.
*/
namespace sta namespace sta
{ {
/** /**
* @brief Container for STM GPIO Pin data. * @ingroup sta_core_stm32_gpio
* * @{
* @ingroup stm32GPIO */
*/
class STM32GpioPin : public GpioPin
{
public:
/**
* @param port GPIO port
* @param pin Pin index
*/
STM32GpioPin(GPIO_TypeDef * port, uint16_t pin);
void setState(GpioPinState state) override;
/**
* @brief Get GPIO port for pin.
*
* @return GPIO port
*/
GPIO_TypeDef * getPort() const;
/**
* @brief Get pin index for pin.
*
* @return Pin index
*/
uint16_t getPin() const;
/**
* @brief Get GPIO port index for pin.
*
* @return GPIO port index
*/
uint8_t getPortIndex() const;
private:
GPIO_TypeDef * port_; /**< GPIO port */
uint16_t pin_; /**< GPIO pin */
};
/** /**
* @brief Interrupt trigger edge. * @brief Container for STM GPIO Pin data.
*/ */
enum class InterruptEdge class STM32GpioPin : public GpioPin
{ {
RISING, /**< Rising edge */ public:
FALLING, /**< Falling edge */ /**
BOTH /**< Rising and falling edge */ * @param port GPIO port
}; * @param pin Pin index
*/
STM32GpioPin(GPIO_TypeDef * port, uint16_t pin);
/** void setState(GpioPinState state) override;
* @brief Check pin EXIT pin configuration.
* /**
* @param pin GPIO pin * @brief Get GPIO port for pin.
* @param edge Interrupt trigger edge *
* @return True if EXIT pin and trigger edge matches * @return GPIO port
*/ */
bool isInterruptEdge(const STM32GpioPin & pin, InterruptEdge edge); GPIO_TypeDef * getPort() const;
/**
* @brief Get pin index for pin.
*
* @return Pin index
*/
uint16_t getPin() const;
/**
* @brief Get GPIO port index for pin.
*
* @return GPIO port index
*/
uint8_t getPortIndex() const;
private:
GPIO_TypeDef * port_; /**< GPIO port */
uint16_t pin_; /**< GPIO pin */
};
/**
* @brief Interrupt trigger edge.
*/
enum class InterruptEdge
{
RISING, /**< Rising edge */
FALLING, /**< Falling edge */
BOTH /**< Rising and falling edge */
};
/**
* @brief Check pin EXIT pin configuration.
*
* @param pin GPIO pin
* @param edge Interrupt trigger edge
* @return True if EXIT pin and trigger edge matches
*/
bool isInterruptEdge(const STM32GpioPin & pin, InterruptEdge edge);
/** @} */
} // namespace sta } // namespace sta
/** /**
@ -95,7 +103,7 @@ namespace sta
* *
* @param label Pin label * @param label Pin label
* *
* @ingroup stm32GPIO * @ingroup sta_core_stm32_gpio
*/ */
#define STA_STM32_GPIO_PIN(label) sta::STM32GpioPin{label##_GPIO_Port, label##_Pin} #define STA_STM32_GPIO_PIN(label) sta::STM32GpioPin{label##_GPIO_Port, label##_Pin}

View File

@ -6,6 +6,13 @@
#define STA_CORE_STM32_HAL_HPP #define STA_CORE_STM32_HAL_HPP
/**
* @defgroup sta_core_stm32 STM32
* @ingroup sta_core_platforms
* @brief Modules implemented for the STM32 platform.
*/
// Include STM32 HAL headers // Include STM32 HAL headers
#include <main.h> #include <main.h>

View File

@ -8,12 +8,12 @@
namespace sta namespace sta
{ {
/** /**
* @brief Initialize global HAL objects. * @brief Initialize global HAL objects.
* *
* @ingroup stm32 * @ingroup sta_core_stm32
*/ */
void initHAL(); void initHAL();
} // namespace sta } // namespace sta

View File

@ -5,12 +5,6 @@
#ifndef STA_CORE_STM32_UART_HPP #ifndef STA_CORE_STM32_UART_HPP
#define STA_CORE_STM32_UART_HPP #define STA_CORE_STM32_UART_HPP
/**
* @defgroup stm32UART UART
* @ingroup stm32
* @brief STM32 UART module.
*/
// Only enable module on STM32 platform w/ HAL UART module enabled // Only enable module on STM32 platform w/ HAL UART module enabled
#include <sta/config.hpp> #include <sta/config.hpp>
@ -27,26 +21,33 @@
#include <sta/uart.hpp> #include <sta/uart.hpp>
/**
* @defgroup sta_core_stm32_uart UART
* @ingroup sta_core_stm32
* @brief STM32 UART module.
*/
namespace sta namespace sta
{ {
/** /**
* @brief Implementation of UART interface using HAL. * @brief Implementation of UART interface using HAL.
* *
* @ingroup stm32UART * @ingroup sta_core_stm32_uart
*/ */
class STM32UART : public UART class STM32UART : public UART
{ {
public: public:
/** /**
* @param handle UART handle * @param handle STM32 HAL handle
*/ */
STM32UART(UART_HandleTypeDef * handle); STM32UART(UART_HandleTypeDef * handle);
void write(const uint8_t * buffer, size_t size) override; void write(const uint8_t * buffer, size_t size) override;
private: private:
UART_HandleTypeDef * handle_; /**< UART handle */ UART_HandleTypeDef * handle_; /**< STM32 HAL handle */
}; };
} // namespace sta } // namespace sta

View File

@ -10,18 +10,18 @@
namespace sta namespace sta
{ {
/** /**
* @brief Signature for millisecond precision time. * @brief Signature for millisecond precision time.
* *
* @return Time in milliseconds * @return Time in milliseconds
*/ */
using TimeMsFn = uint32_t (*)(); using TimeMsFn = uint32_t (*)();
/** /**
* @brief Signature for microseconds precision time. * @brief Signature for microseconds precision time.
* *
* @return Time in microseconds * @return Time in microseconds
*/ */
using TimeUsFn = uint32_t (*)(); using TimeUsFn = uint32_t (*)();
} // namespace sta } // namespace sta

View File

@ -9,41 +9,50 @@
#include <cstdint> #include <cstdint>
/**
* @defgroup sta_core_uart UART
* @ingroup sta_core
* @brief UART interface.
*/
namespace sta namespace sta
{ {
/** /**
* @brief Interface for %UART. * @brief Interface for %UART.
*/ *
class UART * @ingroup sta_core_uart
{ */
public: class UART
/** {
* @brief Write buffer to %UART. public:
* /**
* @param buffer Source buffer * @brief Write buffer to %UART.
* @param size Number of bytes in buffer *
*/ * @param buffer Source buffer
virtual void write(const uint8_t * buffer, size_t size) = 0; * @param size Number of bytes in buffer
*/
virtual void write(const uint8_t * buffer, size_t size) = 0;
/** /**
* @brief Write unsigned integer to %UART. * @brief Write unsigned integer to %UART.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
*/ */
void write(uint8_t value); void write(uint8_t value);
/** /**
* @brief Write unsigned integer to %UART. * @brief Write unsigned integer to %UART.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
*/ */
void write(uint16_t value); void write(uint16_t value);
/** /**
* @brief Write unsigned integer to %UART. * @brief Write unsigned integer to %UART.
* *
* @param value Unsigned integer value * @param value Unsigned integer value
*/ */
void write(uint32_t value); void write(uint32_t value);
}; };
} // namespace sta } // namespace sta

View File

@ -7,23 +7,23 @@
namespace sta namespace sta
{ {
STA_WEAK STA_WEAK
void assert_failed(const char * expr, const char * file, uint32_t line) void assert_failed(const char * expr, const char * file, uint32_t line)
{ {
// printf("%s:%d: Assertion failed: %s", file, line, expr) // printf("%s:%d: Assertion failed: %s", file, line, expr)
STA_DEBUG_PRINT(file); STA_DEBUG_PRINT(file);
STA_DEBUG_PRINT(':'); STA_DEBUG_PRINT(':');
STA_DEBUG_PRINT(line); STA_DEBUG_PRINT(line);
STA_DEBUG_PRINT(": Assertion failed: "); STA_DEBUG_PRINT(": Assertion failed: ");
STA_DEBUG_PRINTLN(expr); STA_DEBUG_PRINTLN(expr);
} }
STA_WEAK STA_WEAK
void assert_halt() void assert_halt()
{ {
STA_BKPT(); STA_BKPT();
while (true); while (true);
} }
} // namespace sta } // namespace sta

View File

@ -4,19 +4,19 @@
namespace sta namespace sta
{ {
AtomicMutex::AtomicMutex() AtomicMutex::AtomicMutex()
: lock_{ATOMIC_FLAG_INIT} : lock_{ATOMIC_FLAG_INIT}
{} {}
void AtomicMutex::acquire() void AtomicMutex::acquire()
{ {
while (lock_.test_and_set()); while (lock_.test_and_set());
} }
void AtomicMutex::release() void AtomicMutex::release()
{ {
lock_.clear(); lock_.clear();
} }
} // namespace sta } // namespace sta

View File

@ -4,29 +4,29 @@
namespace sta namespace sta
{ {
AtomicSignal::AtomicSignal() AtomicSignal::AtomicSignal()
: signal_{false} : signal_{false}
{} {}
void AtomicSignal::notify() void AtomicSignal::notify()
{ {
signal_.store(true); signal_.store(true);
} }
bool AtomicSignal::peek() bool AtomicSignal::peek()
{ {
return signal_.load(); return signal_.load();
} }
bool AtomicSignal::test() bool AtomicSignal::test()
{ {
return signal_.exchange(false); return signal_.exchange(false);
} }
void AtomicSignal::wait() void AtomicSignal::wait()
{ {
while (!signal_.exchange(false)); while (!signal_.exchange(false));
} }
} // namespace sta } // namespace sta

View File

@ -3,24 +3,24 @@
namespace sta namespace sta
{ {
bool operator ==(const CanId & lhs, const CanId & rhs) bool operator ==(const CanId & lhs, const CanId & rhs)
{ {
return (lhs.sid == rhs.sid && lhs.eid == rhs.eid); return (lhs.sid == rhs.sid && lhs.eid == rhs.eid);
} }
bool operator !=(const CanId & lhs, const CanId & rhs) bool operator !=(const CanId & lhs, const CanId & rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
bool operator ==(const CanFrameId & lhs, const CanFrameId & rhs) bool operator ==(const CanFrameId & lhs, const CanFrameId & rhs)
{ {
return (lhs.format == rhs.format && lhs.sid == rhs.sid && lhs.eid == rhs.eid); return (lhs.format == rhs.format && lhs.sid == rhs.sid && lhs.eid == rhs.eid);
} }
bool operator !=(const CanFrameId & lhs, const CanFrameId & rhs) bool operator !=(const CanFrameId & lhs, const CanFrameId & rhs)
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
} // namespace sta } // namespace sta

View File

@ -5,91 +5,91 @@
namespace sta namespace sta
{ {
CanPendingRxFifos::const_iterator::const_iterator(uint32_t rxFlags, uint8_t idx, uint8_t endIdx) CanPendingRxFifos::const_iterator::const_iterator(uint32_t rxFlags, uint8_t idx, uint8_t endIdx)
: rxFlags_{rxFlags}, idx_{idx}, endIdx_{endIdx} : rxFlags_{rxFlags}, idx_{idx}, endIdx_{endIdx}
{} {}
CanPendingRxFifos::const_iterator::const_iterator(const const_iterator & iter) CanPendingRxFifos::const_iterator::const_iterator(const const_iterator & iter)
: rxFlags_{iter.rxFlags_}, idx_{iter.idx_}, endIdx_{iter.endIdx_} : rxFlags_{iter.rxFlags_}, idx_{iter.idx_}, endIdx_{iter.endIdx_}
{} {}
CanPendingRxFifos::const_iterator & CanPendingRxFifos::const_iterator::operator=(const const_iterator & iter) CanPendingRxFifos::const_iterator & CanPendingRxFifos::const_iterator::operator=(const const_iterator & iter)
{ {
rxFlags_ = iter.rxFlags_; rxFlags_ = iter.rxFlags_;
idx_ = iter.idx_; idx_ = iter.idx_;
endIdx_ = iter.endIdx_; endIdx_ = iter.endIdx_;
return *this; return *this;
} }
bool CanPendingRxFifos::const_iterator::operator==(const const_iterator & iter) const bool CanPendingRxFifos::const_iterator::operator==(const const_iterator & iter) const
{ {
return (rxFlags_ == iter.rxFlags_) && (idx_ == iter.idx_) && (endIdx_ == iter.endIdx_); return (rxFlags_ == iter.rxFlags_) && (idx_ == iter.idx_) && (endIdx_ == iter.endIdx_);
} }
bool CanPendingRxFifos::const_iterator::operator!=(const const_iterator & iter) const bool CanPendingRxFifos::const_iterator::operator!=(const const_iterator & iter) const
{ {
return !(*this == iter); return !(*this == iter);
} }
CanPendingRxFifos::const_iterator & CanPendingRxFifos::const_iterator::operator++() CanPendingRxFifos::const_iterator & CanPendingRxFifos::const_iterator::operator++()
{ {
while (idx_ < endIdx_) while (idx_ < endIdx_)
{ {
++idx_; ++idx_;
if (isRxPending()) if (isRxPending())
{ {
break; break;
} }
} }
return *this; return *this;
} }
CanPendingRxFifos::const_iterator CanPendingRxFifos::const_iterator::operator++(int) CanPendingRxFifos::const_iterator CanPendingRxFifos::const_iterator::operator++(int)
{ {
uint8_t oldIdx = idx_; uint8_t oldIdx = idx_;
while (idx_ < endIdx_) while (idx_ < endIdx_)
{ {
++idx_; ++idx_;
if (isRxPending()) if (isRxPending())
{ {
break; break;
} }
} }
return const_iterator(rxFlags_, oldIdx, endIdx_); return const_iterator(rxFlags_, oldIdx, endIdx_);
} }
CanPendingRxFifos::const_iterator::reference CanPendingRxFifos::const_iterator::operator*() const CanPendingRxFifos::const_iterator::reference CanPendingRxFifos::const_iterator::operator*() const
{ {
STA_ASSERT_MSG(idx_ != endIdx_, "Dereferencing out-of-bounds iterator"); STA_ASSERT_MSG(idx_ != endIdx_, "Dereferencing out-of-bounds iterator");
return idx_; return idx_;
} }
bool CanPendingRxFifos::const_iterator::isRxPending() const bool CanPendingRxFifos::const_iterator::isRxPending() const
{ {
return ( (rxFlags_ >> idx_) & 0x1 ); return ( (rxFlags_ >> idx_) & 0x1 );
} }
CanPendingRxFifos::CanPendingRxFifos(uint32_t rxFlags, uint8_t numFifos) CanPendingRxFifos::CanPendingRxFifos(uint32_t rxFlags, uint8_t numFifos)
: rxFlags_{rxFlags}, numFifos_{numFifos} : rxFlags_{rxFlags}, numFifos_{numFifos}
{} {}
CanPendingRxFifos::const_iterator CanPendingRxFifos::begin() const CanPendingRxFifos::const_iterator CanPendingRxFifos::begin() const
{ {
return const_iterator(rxFlags_, 0, numFifos_); return const_iterator(rxFlags_, 0, numFifos_);
} }
CanPendingRxFifos::const_iterator CanPendingRxFifos::end() const CanPendingRxFifos::const_iterator CanPendingRxFifos::end() const
{ {
return const_iterator(rxFlags_, numFifos_, numFifos_); return const_iterator(rxFlags_, numFifos_, numFifos_);
} }
} // namespace sta } // namespace sta

View File

@ -16,14 +16,14 @@ using PlatformUART = sta::STM32UART;
namespace namespace
{ {
// Create platform specific serial interface // Create platform specific serial interface
PlatformUART platformDebugSerial(&STA_DEBUG_SERIAL_UART); PlatformUART platformDebugSerial(&STA_DEBUG_SERIAL_UART);
} }
namespace sta namespace sta
{ {
// Create debug serial object using platform specific serial interface // Create debug serial object using platform specific serial interface
PrintableUART DebugSerial(&platformDebugSerial); PrintableUART DebugSerial(&platformDebugSerial);
} // namespace sta } // namespace sta

View File

@ -3,18 +3,18 @@
namespace sta namespace sta
{ {
/** /**
* @brief Dummy mutex implementation with no access control. * @brief Dummy mutex implementation with no access control.
*/ */
class DummyMutex : public Mutex class DummyMutex : public Mutex
{ {
public: public:
void acquire() override {} void acquire() override {}
void release() override {} void release() override {}
}; };
static DummyMutex dummyMutex; static DummyMutex dummyMutex;
Mutex * Mutex::ALWAYS_FREE = &dummyMutex; Mutex * Mutex::ALWAYS_FREE = &dummyMutex;
} // namespace sta } // namespace sta

View File

@ -10,202 +10,202 @@
namespace sta namespace sta
{ {
PrintableUART::PrintableUART(UART * intf) PrintableUART::PrintableUART(UART * intf)
: intf_{intf} : intf_{intf}
{ {
STA_ASSERT(intf != nullptr); STA_ASSERT(intf != nullptr);
} }
void PrintableUART::print(char c) void PrintableUART::print(char c)
{ {
print(&c, 1); print(&c, 1);
} }
void PrintableUART::print(bool b) void PrintableUART::print(bool b)
{ {
print(b ? "true" : "false"); print(b ? "true" : "false");
} }
void PrintableUART::print(double d) void PrintableUART::print(double d)
{ {
char buffer[64]; char buffer[64];
snprintf(buffer, sizeof(buffer), "%f", d); snprintf(buffer, sizeof(buffer), "%f", d);
print(buffer); print(buffer);
} }
void PrintableUART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::print(uint8_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
printBase(num, base, "%" PRIu8, sizeof(num)); printBase(num, base, "%" PRIu8, sizeof(num));
} }
void PrintableUART::print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::print(uint16_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
printBase(num, base, "%" PRIu16, sizeof(num)); printBase(num, base, "%" PRIu16, sizeof(num));
} }
void PrintableUART::print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::print(uint32_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
printBase(num, base, "%" PRIu32, sizeof(num)); printBase(num, base, "%" PRIu32, sizeof(num));
} }
void PrintableUART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::print(size_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
printBase(num, base, "%z", sizeof(num)); printBase(num, base, "%z", sizeof(num));
} }
void PrintableUART::print(const char * str) void PrintableUART::print(const char * str)
{ {
print(str, strlen(str)); print(str, strlen(str));
} }
void PrintableUART::print(const char * str, size_t length) void PrintableUART::print(const char * str, size_t length)
{ {
intf_->write(reinterpret_cast<const uint8_t *>(str), length); intf_->write(reinterpret_cast<const uint8_t *>(str), length);
} }
void PrintableUART::println() void PrintableUART::println()
{ {
print("\r\n", 2); print("\r\n", 2);
} }
void PrintableUART::println(char c) void PrintableUART::println(char c)
{ {
print(&c, 1); print(&c, 1);
println(); println();
} }
void PrintableUART::println(bool b) void PrintableUART::println(bool b)
{ {
print(b); print(b);
println(); println();
} }
void PrintableUART::println(double d) void PrintableUART::println(double d)
{ {
print(d); print(d);
println(); println();
} }
void PrintableUART::println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::println(uint8_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
print(num, base); print(num, base);
println(); println();
} }
void PrintableUART::println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::println(uint16_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
print(num, base); print(num, base);
println(); println();
} }
void PrintableUART::println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::println(uint32_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
print(num, base); print(num, base);
println(); println();
} }
void PrintableUART::println(size_t num, IntegerBase base /* = IntegerBase::DEC */) void PrintableUART::println(size_t num, IntegerBase base /* = IntegerBase::DEC */)
{ {
print(num, base); print(num, base);
println(); println();
} }
void PrintableUART::println(const char * str) void PrintableUART::println(const char * str)
{ {
println(str, strlen(str)); println(str, strlen(str));
} }
void PrintableUART::println(const char * str, size_t length) void PrintableUART::println(const char * str, size_t length)
{ {
print(str, length); print(str, length);
println(); println();
} }
void PrintableUART::printBase(uintmax_t num, IntegerBase base, const char * fmt, size_t size) void PrintableUART::printBase(uintmax_t num, IntegerBase base, const char * fmt, size_t size)
{ {
switch (base) switch (base)
{ {
case IntegerBase::DEC: case IntegerBase::DEC:
printDec(num, fmt); printDec(num, fmt);
break; break;
case IntegerBase::BIN: case IntegerBase::BIN:
// Digits in base 2 = size in bytes * 8 // Digits in base 2 = size in bytes * 8
printBin(num, size * 8); printBin(num, size * 8);
break; break;
case IntegerBase::HEX: case IntegerBase::HEX:
// Digits in base 16 = size in bytes * 2 // Digits in base 16 = size in bytes * 2
printHex(num, size * 2); printHex(num, size * 2);
break; break;
default: default:
print("<invalid_base>"); print("<invalid_base>");
} }
} }
void PrintableUART::printDec(uintmax_t num, const char * fmt) void PrintableUART::printDec(uintmax_t num, const char * fmt)
{ {
char buffer[64]; char buffer[64];
snprintf(buffer, sizeof(buffer), fmt, static_cast<uint32_t>(num)); snprintf(buffer, sizeof(buffer), fmt, static_cast<uint32_t>(num));
print(buffer); print(buffer);
} }
void PrintableUART::printBin(uintmax_t value, size_t digits) void PrintableUART::printBin(uintmax_t value, size_t digits)
{ {
// Need 8 digits for every byte // Need 8 digits for every byte
char buffer[sizeof(value) * 8]; char buffer[sizeof(value) * 8];
// Check bounds // Check bounds
if (digits > sizeof(buffer)) if (digits > sizeof(buffer))
{ {
print("<bin_value_too_big>"); print("<bin_value_too_big>");
return; return;
} }
// Nothing to do // Nothing to do
if (digits == 0) if (digits == 0)
return; return;
for (size_t i = 0; i < digits; ++i) for (size_t i = 0; i < digits; ++i)
{ {
// Convert bit to '0' or '1' // Convert bit to '0' or '1'
// First digit in buffer is MSB in value, so shift from high to low // First digit in buffer is MSB in value, so shift from high to low
buffer[i] = '0' + ((value >> (digits - 1 - i)) & 0x1); buffer[i] = '0' + ((value >> (digits - 1 - i)) & 0x1);
} }
print(buffer, digits); print(buffer, digits);
} }
void PrintableUART::printHex(uintmax_t value, size_t digits) void PrintableUART::printHex(uintmax_t value, size_t digits)
{ {
// Need 2 digits for every byte // Need 2 digits for every byte
char buffer[sizeof(value) * 2]; char buffer[sizeof(value) * 2];
// Check bounds // Check bounds
if (digits > sizeof(buffer)) if (digits > sizeof(buffer))
{ {
print("<hex_value_too_big>"); print("<hex_value_too_big>");
return; return;
} }
// Nothing to do // Nothing to do
if (digits == 0) if (digits == 0)
return; return;
for (size_t i = 0; i < digits; ++i) for (size_t i = 0; i < digits; ++i)
{ {
// Convert 4 bits to hex // Convert 4 bits to hex
// First digit in buffer is 4 MSBs in value, so shift from high to low // First digit in buffer is 4 MSBs in value, so shift from high to low
uint8_t hex = ((value >> ((digits - 1 - i) * 4)) & 0xF); uint8_t hex = ((value >> ((digits - 1 - i) * 4)) & 0xF);
if (hex > 9) if (hex > 9)
buffer[i] = 'A' + (hex - 10); buffer[i] = 'A' + (hex - 10);
else else
buffer[i] = '0' + hex; buffer[i] = '0' + hex;
} }
print(buffer, digits); print(buffer, digits);
} }
} // namespace sta } // namespace sta

View File

@ -7,167 +7,167 @@
namespace sta namespace sta
{ {
STM32CanController::STM32CanController(CAN_HandleTypeDef * handle) STM32CanController::STM32CanController(CAN_HandleTypeDef * handle)
: handle_{handle} : handle_{handle}
{ {
initFilters(); initFilters();
} }
void STM32CanController::enableRxInterrupts() void STM32CanController::enableRxInterrupts()
{ {
HAL_CAN_ActivateNotification(handle_, HAL_CAN_ActivateNotification(handle_,
CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING
); );
} }
void STM32CanController::start() void STM32CanController::start()
{ {
HAL_CAN_Start(handle_); HAL_CAN_Start(handle_);
} }
void STM32CanController::stop() void STM32CanController::stop()
{ {
HAL_CAN_Stop(handle_); HAL_CAN_Stop(handle_);
} }
bool STM32CanController::sendFrame(const CanTxHeader & header, const uint8_t * payload) bool STM32CanController::sendFrame(const CanTxHeader & header, const uint8_t * payload)
{ {
STA_ASSERT_MSG(header.payloadLength <= 8, "CAN 2.0B payload size exceeded"); STA_ASSERT_MSG(header.payloadLength <= 8, "CAN 2.0B payload size exceeded");
CAN_TxHeaderTypeDef halHeader; CAN_TxHeaderTypeDef halHeader;
if (header.id.format == CanIdFormat::STD) if (header.id.format == CanIdFormat::STD)
{ {
halHeader.StdId = header.id.sid & 0x7FF; halHeader.StdId = header.id.sid & 0x7FF;
halHeader.IDE = CAN_ID_STD; halHeader.IDE = CAN_ID_STD;
} }
else else
{ {
// Combine SID and EID // Combine SID and EID
halHeader.ExtId = ((header.id.sid & 0x7FF) << 18) | (header.id.eid & 0x3FFFF); halHeader.ExtId = ((header.id.sid & 0x7FF) << 18) | (header.id.eid & 0x3FFFF);
halHeader.IDE = CAN_ID_EXT; halHeader.IDE = CAN_ID_EXT;
} }
halHeader.DLC = header.payloadLength; halHeader.DLC = header.payloadLength;
uint32_t mailbox; // Don't care uint32_t mailbox; // Don't care
return (HAL_OK == HAL_CAN_AddTxMessage(handle_, &halHeader, const_cast<uint8_t *>(payload), &mailbox)); return (HAL_OK == HAL_CAN_AddTxMessage(handle_, &halHeader, const_cast<uint8_t *>(payload), &mailbox));
} }
bool STM32CanController::receiveFrame(uint8_t fifo, CanRxHeader * header, uint8_t * payload) bool STM32CanController::receiveFrame(uint8_t fifo, CanRxHeader * header, uint8_t * payload)
{ {
// Check if message is available // Check if message is available
if (HAL_CAN_GetRxFifoFillLevel(handle_, fifo) == 0) if (HAL_CAN_GetRxFifoFillLevel(handle_, fifo) == 0)
return false; return false;
// Retrieve message // Retrieve message
CAN_RxHeaderTypeDef halHeader; CAN_RxHeaderTypeDef halHeader;
HAL_CAN_GetRxMessage(handle_, fifo, &halHeader, payload); HAL_CAN_GetRxMessage(handle_, fifo, &halHeader, payload);
if (halHeader.IDE == CAN_ID_STD) if (halHeader.IDE == CAN_ID_STD)
{ {
header->id.format = CanIdFormat::STD; header->id.format = CanIdFormat::STD;
header->id.sid = halHeader.StdId; header->id.sid = halHeader.StdId;
header->id.eid = 0; header->id.eid = 0;
} }
else else
{ {
header->id.format = CanIdFormat::EXT; header->id.format = CanIdFormat::EXT;
// Separate SID and EID // Separate SID and EID
header->id.sid = (halHeader.ExtId >> 18); header->id.sid = (halHeader.ExtId >> 18);
header->id.eid = halHeader.ExtId & 0x3FFFF; header->id.eid = halHeader.ExtId & 0x3FFFF;
} }
// No conversion required for CAN 2B standard // No conversion required for CAN 2B standard
header->payloadLength = halHeader.DLC; header->payloadLength = halHeader.DLC;
header->timestamp = halHeader.Timestamp; header->timestamp = halHeader.Timestamp;
header->filter = halHeader.FilterMatchIndex; header->filter = halHeader.FilterMatchIndex;
return true; return true;
} }
uint32_t STM32CanController::getRxFifoFlags() uint32_t STM32CanController::getRxFifoFlags()
{ {
// //
return (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO0) != 0) return (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO0) != 0)
| (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO1) != 0) << 1; | (HAL_CAN_GetRxFifoFillLevel(handle_, CAN_RX_FIFO1) != 0) << 1;
} }
void STM32CanController::configureFilter(uint8_t idx, const CanFilter & filter, bool active /* = false */) void STM32CanController::configureFilter(uint8_t idx, const CanFilter & filter, bool active /* = false */)
{ {
CAN_FilterTypeDef * config = &filters_[idx]; CAN_FilterTypeDef * config = &filters_[idx];
if (filter.type == CanFilterIdFormat::STD) if (filter.type == CanFilterIdFormat::STD)
{ {
config->FilterIdHigh = 0; config->FilterIdHigh = 0;
config->FilterIdLow = filter.obj.sid & 0x7FF; config->FilterIdLow = filter.obj.sid & 0x7FF;
config->FilterMaskIdHigh = 0; config->FilterMaskIdHigh = 0;
config->FilterMaskIdLow = filter.mask.sid & 0x7FF; config->FilterMaskIdLow = filter.mask.sid & 0x7FF;
} }
else else
{ {
config->FilterIdHigh = ((filter.obj.sid & 0x7FF) << 2) | ((filter.obj.eid >> 16) & 0x3); config->FilterIdHigh = ((filter.obj.sid & 0x7FF) << 2) | ((filter.obj.eid >> 16) & 0x3);
config->FilterIdLow = filter.obj.eid & 0xFFFF; config->FilterIdLow = filter.obj.eid & 0xFFFF;
config->FilterMaskIdHigh = ((filter.mask.sid & 0x7FF) << 2) | ((filter.mask.eid >> 16) & 0x3); config->FilterMaskIdHigh = ((filter.mask.sid & 0x7FF) << 2) | ((filter.mask.eid >> 16) & 0x3);
config->FilterMaskIdLow = filter.mask.eid & 0xFFFF; config->FilterMaskIdLow = filter.mask.eid & 0xFFFF;
} }
config->FilterFIFOAssignment = filter.fifo; config->FilterFIFOAssignment = filter.fifo;
config->FilterActivation = (active ? CAN_FILTER_ENABLE : CAN_FILTER_DISABLE); config->FilterActivation = (active ? CAN_FILTER_ENABLE : CAN_FILTER_DISABLE);
HAL_CAN_ConfigFilter(handle_, config); HAL_CAN_ConfigFilter(handle_, config);
} }
void STM32CanController::enableFilter(uint8_t idx) void STM32CanController::enableFilter(uint8_t idx)
{ {
CAN_FilterTypeDef * config = &filters_[idx]; CAN_FilterTypeDef * config = &filters_[idx];
config->FilterActivation = CAN_FILTER_ENABLE; config->FilterActivation = CAN_FILTER_ENABLE;
HAL_CAN_ConfigFilter(handle_, config); HAL_CAN_ConfigFilter(handle_, config);
} }
void STM32CanController::disableFilter(uint8_t idx) void STM32CanController::disableFilter(uint8_t idx)
{ {
CAN_FilterTypeDef * config = &filters_[idx]; CAN_FilterTypeDef * config = &filters_[idx];
config->FilterActivation = CAN_FILTER_DISABLE; config->FilterActivation = CAN_FILTER_DISABLE;
HAL_CAN_ConfigFilter(handle_, config); HAL_CAN_ConfigFilter(handle_, config);
} }
void STM32CanController::clearFilters() void STM32CanController::clearFilters()
{ {
for (uint32_t i = 0; i < MAX_FILTER_COUNT; ++i) for (uint32_t i = 0; i < MAX_FILTER_COUNT; ++i)
{ {
CAN_FilterTypeDef * config = &filters_[i]; CAN_FilterTypeDef * config = &filters_[i];
// Only disable active filters // Only disable active filters
if (config->FilterActivation == CAN_FILTER_ENABLE) if (config->FilterActivation == CAN_FILTER_ENABLE)
{ {
config->FilterActivation = CAN_FILTER_DISABLE; config->FilterActivation = CAN_FILTER_DISABLE;
HAL_CAN_ConfigFilter(handle_, config); HAL_CAN_ConfigFilter(handle_, config);
} }
} }
} }
void STM32CanController::initFilters() void STM32CanController::initFilters()
{ {
for (uint32_t i = 0; i < MAX_FILTER_COUNT; ++i) for (uint32_t i = 0; i < MAX_FILTER_COUNT; ++i)
{ {
CAN_FilterTypeDef * config = &filters_[i]; CAN_FilterTypeDef * config = &filters_[i];
config->FilterBank = i; config->FilterBank = i;
config->FilterMode = CAN_FILTERMODE_IDMASK; config->FilterMode = CAN_FILTERMODE_IDMASK;
config->FilterScale = CAN_FILTERSCALE_32BIT; config->FilterScale = CAN_FILTERSCALE_32BIT;
config->FilterActivation = CAN_FILTER_DISABLE; config->FilterActivation = CAN_FILTER_DISABLE;
config->SlaveStartFilterBank = MAX_FILTER_COUNT; config->SlaveStartFilterBank = MAX_FILTER_COUNT;
} }
} }
} // namespace sta } // namespace sta
@ -177,31 +177,31 @@ namespace sta
namespace sta namespace sta
{ {
STM32CanController CanBus(&STA_STM32_CAN_GLOBAL); STM32CanController CanBus(&STA_STM32_CAN_GLOBAL);
STA_WEAK STA_WEAK
void CanBus_RxPendingCallback() void CanBus_RxPendingCallback()
{} {}
} // namespace sta } // namespace sta
extern "C" extern "C"
{ {
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{ {
if (hcan == &STA_STM32_CAN_GLOBAL) if (hcan == &STA_STM32_CAN_GLOBAL)
{ {
sta::CanBus_RxPendingCallback(); sta::CanBus_RxPendingCallback();
} }
} }
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{ {
if (hcan == &STA_STM32_CAN_GLOBAL) if (hcan == &STA_STM32_CAN_GLOBAL)
{ {
sta::CanBus_RxPendingCallback(); sta::CanBus_RxPendingCallback();
} }
} }
} }
#endif // STA_STM32_CAN_GLOBAL #endif // STA_STM32_CAN_GLOBAL

View File

@ -10,10 +10,10 @@
namespace sta namespace sta
{ {
void delayMs(uint32_t ms) void delayMs(uint32_t ms)
{ {
HAL_Delay(ms); HAL_Delay(ms);
} }
} // namespace sta } // namespace sta
@ -27,46 +27,46 @@ namespace sta
namespace sta namespace sta
{ {
uint32_t gDelayUsMul = 1; uint32_t gDelayUsMul = 1;
void delayUs(uint32_t us) void delayUs(uint32_t us)
{ {
__HAL_TIM_SET_COUNTER(&STA_STM32_DELAY_US_TIM, 0); __HAL_TIM_SET_COUNTER(&STA_STM32_DELAY_US_TIM, 0);
while (__HAL_TIM_GET_COUNTER(&STA_STM32_DELAY_US_TIM) < us * gDelayUsMul); while (__HAL_TIM_GET_COUNTER(&STA_STM32_DELAY_US_TIM) < us * gDelayUsMul);
} }
bool isValidDelayUsTIM() bool isValidDelayUsTIM()
{ {
// Get PCLK multiplier for TIM clock // Get PCLK multiplier for TIM clock
uint32_t pclkMul = 1; uint32_t pclkMul = 1;
switch (STA_STM32_DELAY_US_TIM.Init.ClockDivision) switch (STA_STM32_DELAY_US_TIM.Init.ClockDivision)
{ {
case TIM_CLOCKDIVISION_DIV1: case TIM_CLOCKDIVISION_DIV1:
pclkMul = 1; pclkMul = 1;
break; break;
case TIM_CLOCKDIVISION_DIV2: case TIM_CLOCKDIVISION_DIV2:
pclkMul = 2; pclkMul = 2;
break; break;
case TIM_CLOCKDIVISION_DIV4: case TIM_CLOCKDIVISION_DIV4:
pclkMul = 4; pclkMul = 4;
break; break;
default: default:
STA_ASSERT(false); STA_ASSERT(false);
STA_UNREACHABLE(); STA_UNREACHABLE();
} }
// Calculate TIM clock frequency // Calculate TIM clock frequency
uint32_t clkFreq = pclkMul * STA_STM32_GET_HANDLE_PCLK_FREQ_FN(STA_STM32_DELAY_US_TIM)(); uint32_t clkFreq = pclkMul * STA_STM32_GET_HANDLE_PCLK_FREQ_FN(STA_STM32_DELAY_US_TIM)();
// Calculate update frequency based on prescaler value // Calculate update frequency based on prescaler value
uint32_t prescaler = (STA_STM32_DELAY_US_TIM.Init.Prescaler) ? STA_STM32_DELAY_US_TIM.Init.Prescaler : 1; uint32_t prescaler = (STA_STM32_DELAY_US_TIM.Init.Prescaler) ? STA_STM32_DELAY_US_TIM.Init.Prescaler : 1;
uint32_t updateFreq = clkFreq / prescaler; uint32_t updateFreq = clkFreq / prescaler;
gDelayUsMul = updateFreq / 1000000; gDelayUsMul = updateFreq / 1000000;
// TIM must have at least microsecond precision (>= 1 MHz frequency) // TIM must have at least microsecond precision (>= 1 MHz frequency)
return (updateFreq >= 1000000); return (updateFreq >= 1000000);
} }
} // namespace sta } // namespace sta
#endif // STA_STM32_DELAY_US_TIM #endif // STA_STM32_DELAY_US_TIM

View File

@ -7,76 +7,76 @@
namespace sta namespace sta
{ {
STM32GpioPin::STM32GpioPin(GPIO_TypeDef * port, uint16_t pin) STM32GpioPin::STM32GpioPin(GPIO_TypeDef * port, uint16_t pin)
: port_{port}, pin_{pin} : port_{port}, pin_{pin}
{ {
STA_ASSERT(port != nullptr); STA_ASSERT(port != nullptr);
} }
void STM32GpioPin::setState(GpioPinState state) void STM32GpioPin::setState(GpioPinState state)
{ {
HAL_GPIO_WritePin(port_, pin_, (state == GpioPinState::LOW) ? GPIO_PIN_RESET : GPIO_PIN_SET); HAL_GPIO_WritePin(port_, pin_, (state == GpioPinState::LOW) ? GPIO_PIN_RESET : GPIO_PIN_SET);
} }
GPIO_TypeDef * STM32GpioPin::getPort() const GPIO_TypeDef * STM32GpioPin::getPort() const
{ {
return port_; return port_;
} }
uint16_t STM32GpioPin::getPin() const uint16_t STM32GpioPin::getPin() const
{ {
return pin_; return pin_;
} }
uint8_t STM32GpioPin::getPortIndex() const uint8_t STM32GpioPin::getPortIndex() const
{ {
return GPIO_GET_INDEX(port_); return GPIO_GET_INDEX(port_);
} }
bool isInterruptEdge(const STM32GpioPin & gpioPin, InterruptEdge edge) bool isInterruptEdge(const STM32GpioPin & gpioPin, InterruptEdge edge)
{ {
uint32_t pin = gpioPin.getPin(); uint32_t pin = gpioPin.getPin();
for (uint32_t i = 0; i < 8 * sizeof(pin); ++i) for (uint32_t i = 0; i < 8 * sizeof(pin); ++i)
{ {
uint32_t ioPos = 1U << i; uint32_t ioPos = 1U << i;
if (pin & ioPos) if (pin & ioPos)
{ {
// Check input mode // Check input mode
uint32_t mode = (gpioPin.getPort()->MODER >> (2U * i)) & GPIO_MODE; uint32_t mode = (gpioPin.getPort()->MODER >> (2U * i)) & GPIO_MODE;
if (mode != MODE_INPUT) if (mode != MODE_INPUT)
{ {
return false; return false;
} }
// Is EXTI configured? // Is EXTI configured?
if (EXTI->IMR & ioPos) if (EXTI->IMR & ioPos)
{ {
bool rising = (EXTI->RTSR & ioPos); bool rising = (EXTI->RTSR & ioPos);
bool falling = (EXTI->FTSR & ioPos); bool falling = (EXTI->FTSR & ioPos);
switch (edge) switch (edge)
{ {
case InterruptEdge::RISING: case InterruptEdge::RISING:
return rising; return rising;
case InterruptEdge::FALLING: case InterruptEdge::FALLING:
return falling; return falling;
case InterruptEdge::BOTH: case InterruptEdge::BOTH:
return rising && falling; return rising && falling;
default: default:
STA_ASSERT(false); STA_ASSERT(false);
STA_UNREACHABLE(); STA_UNREACHABLE();
} }
} }
} }
} }
return false; return false;
} }
} // namespace sta } // namespace sta

View File

@ -15,14 +15,14 @@
namespace sta namespace sta
{ {
void initHAL() void initHAL()
{ {
#ifdef STA_STM32_DELAY_US_TIM #ifdef STA_STM32_DELAY_US_TIM
// Validate TIM used for delayUs // Validate TIM used for delayUs
extern bool isValidDelayUsTIM(); extern bool isValidDelayUsTIM();
STA_ASSERT(isValidDelayUsTIM()); STA_ASSERT(isValidDelayUsTIM());
// Start timer base // Start timer base
HAL_TIM_Base_Start(&STA_STM32_DELAY_US_TIM); HAL_TIM_Base_Start(&STA_STM32_DELAY_US_TIM);
#endif // STA_STM32_DELAY_US_TIM #endif // STA_STM32_DELAY_US_TIM
} }
} // namespace sta } // namespace sta

View File

@ -6,19 +6,19 @@
namespace sta namespace sta
{ {
STM32UART::STM32UART(UART_HandleTypeDef * handle) STM32UART::STM32UART(UART_HandleTypeDef * handle)
: handle_{handle} : handle_{handle}
{ {
STA_ASSERT(handle != nullptr); STA_ASSERT(handle != nullptr);
} }
void STM32UART::write(const uint8_t * buffer, size_t size) void STM32UART::write(const uint8_t * buffer, size_t size)
{ {
STA_ASSERT(buffer != nullptr); STA_ASSERT(buffer != nullptr);
HAL_UART_Transmit(handle_, const_cast<uint8_t *>(buffer), size, HAL_MAX_DELAY); HAL_UART_Transmit(handle_, const_cast<uint8_t *>(buffer), size, HAL_MAX_DELAY);
} }
} // namespace sta } // namespace sta

View File

@ -9,21 +9,21 @@
namespace sta namespace sta
{ {
void UART::write(uint8_t value) void UART::write(uint8_t value)
{ {
// TODO Handle endian-ness // TODO Handle endian-ness
write(&value, 1); write(&value, 1);
} }
void UART::write(uint16_t value) void UART::write(uint16_t value)
{ {
// TODO Handle endian-ness // TODO Handle endian-ness
write(reinterpret_cast<uint8_t *>(&value), sizeof(value)); write(reinterpret_cast<uint8_t *>(&value), sizeof(value));
} }
void UART::write(uint32_t value) void UART::write(uint32_t value)
{ {
// TODO Handle endian-ness // TODO Handle endian-ness
write(reinterpret_cast<uint8_t *>(&value), sizeof(value)); write(reinterpret_cast<uint8_t *>(&value), sizeof(value));
} }
} // namespace sta } // namespace sta