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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,23 +8,25 @@
namespace sta
{
/**
* @brief Interface for mutex objects.
*/
class Mutex
{
public:
/**
* @brief Block until mutex has been acquired.
*/
virtual void acquire() = 0;
/**
* @brief Release mutex.
*/
virtual void release() = 0;
/**
* @brief Interface for mutex objects.
*
* @ingroup sta_core
*/
class Mutex
{
public:
/**
* @brief Block until mutex has been acquired.
*/
virtual void acquire() = 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,11 +5,6 @@
#ifndef 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
#include <sta/config.hpp>
@ -26,68 +21,81 @@
#include <sta/gpio_pin.hpp>
/**
* @defgroup sta_core_stm32_gpio GPIO
* @ingroup sta_core_stm32
* @brief STM32 GPIO module.
*/
namespace sta
{
/**
* @brief Container for STM GPIO Pin data.
*
* @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 */
};
/**
* @ingroup sta_core_stm32_gpio
* @{
*/
/**
* @brief Interrupt trigger edge.
*/
enum class InterruptEdge
{
RISING, /**< Rising edge */
FALLING, /**< Falling edge */
BOTH /**< Rising and falling edge */
};
/**
* @brief Container for STM GPIO Pin data.
*/
class STM32GpioPin : public GpioPin
{
public:
/**
* @param port GPIO port
* @param pin Pin index
*/
STM32GpioPin(GPIO_TypeDef * port, uint16_t pin);
/**
* @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);
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.
*/
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
/**
@ -95,7 +103,7 @@ namespace sta
*
* @param label Pin label
*
* @ingroup stm32GPIO
* @ingroup sta_core_stm32_gpio
*/
#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
/**
* @defgroup sta_core_stm32 STM32
* @ingroup sta_core_platforms
* @brief Modules implemented for the STM32 platform.
*/
// Include STM32 HAL headers
#include <main.h>

View File

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

View File

@ -5,12 +5,6 @@
#ifndef 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
#include <sta/config.hpp>
@ -27,26 +21,33 @@
#include <sta/uart.hpp>
/**
* @defgroup sta_core_stm32_uart UART
* @ingroup sta_core_stm32
* @brief STM32 UART module.
*/
namespace sta
{
/**
* @brief Implementation of UART interface using HAL.
*
* @ingroup stm32UART
*/
class STM32UART : public UART
{
public:
/**
* @param handle UART handle
*/
STM32UART(UART_HandleTypeDef * handle);
/**
* @brief Implementation of UART interface using HAL.
*
* @ingroup sta_core_stm32_uart
*/
class STM32UART : public UART
{
public:
/**
* @param handle STM32 HAL 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:
UART_HandleTypeDef * handle_; /**< UART handle */
};
private:
UART_HandleTypeDef * handle_; /**< STM32 HAL handle */
};
} // namespace sta

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,19 +6,19 @@
namespace sta
{
STM32UART::STM32UART(UART_HandleTypeDef * handle)
: handle_{handle}
{
STA_ASSERT(handle != nullptr);
}
STM32UART::STM32UART(UART_HandleTypeDef * handle)
: handle_{handle}
{
STA_ASSERT(handle != nullptr);
}
void STM32UART::write(const uint8_t * buffer, size_t size)
{
STA_ASSERT(buffer != nullptr);
void STM32UART::write(const uint8_t * buffer, size_t size)
{
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

View File

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