mirror of
https://git.intern.spaceteamaachen.de/ALPAKA/sta-core.git
synced 2025-08-02 09:21:54 +00:00
Move CAN interface to STA Core library
This commit is contained in:
parent
92e3dd474b
commit
e2854fceee
100
include/sta/intf/can/controller.hpp
Normal file
100
include/sta/intf/can/controller.hpp
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief CAN controller driver interface.
|
||||
*/
|
||||
#ifndef STA_INTF_CAN_CONTROLLER_HPP
|
||||
#define STA_INTF_CAN_CONTROLLER_HPP
|
||||
|
||||
/**
|
||||
* @defgroup can CAN
|
||||
* @brief CAN Controller interface definition.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup canAPI API
|
||||
* @ingroup can
|
||||
* @brief Public library interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup canBuildConfig Build config
|
||||
* @ingroup can
|
||||
* @brief Build configuration options.
|
||||
*/
|
||||
|
||||
#include <sta/intf/can/filter.hpp>
|
||||
#include <sta/intf/can/headers.hpp>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
/**
|
||||
* @brief CAN controller driver interface.
|
||||
*
|
||||
* @ingroup canAPI
|
||||
*/
|
||||
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 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;
|
||||
|
||||
|
||||
// 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;
|
||||
};
|
||||
} // namespace sta
|
||||
|
||||
|
||||
#endif // STA_INTF_CAN_CONTROLLER_HPP
|
49
include/sta/intf/can/filter.hpp
Normal file
49
include/sta/intf/can/filter.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief CAN message filter types.
|
||||
*/
|
||||
#ifndef STA_INFT_CAN_FILTER_HPP
|
||||
#define STA_INFT_CAN_FILTER_HPP
|
||||
|
||||
#include <sta/intf/can/id.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
/**
|
||||
* @defgroup canFilter Filters
|
||||
* @ingroup canAPI
|
||||
* @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 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 */
|
||||
};
|
||||
} // namespace sta
|
||||
|
||||
|
||||
#endif // STA_INFT_CAN_FILTER_HPP
|
48
include/sta/intf/can/headers.hpp
Normal file
48
include/sta/intf/can/headers.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief CAN frame headers.
|
||||
*/
|
||||
#ifndef STA_INTF_CAN_HEADERS_HPP
|
||||
#define STA_INTF_CAN_HEADERS_HPP
|
||||
|
||||
#include <sta/intf/can/id.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
/**
|
||||
* @defgroup canHeader Frame headers
|
||||
* @ingroup canAPI
|
||||
* @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 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 */
|
||||
};
|
||||
} // namespace sta
|
||||
|
||||
|
||||
#endif // STA_INTF_CAN_HEADERS_HPP
|
82
include/sta/intf/can/id.hpp
Normal file
82
include/sta/intf/can/id.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief CAN frame ID types.
|
||||
*/
|
||||
#ifndef STA_INTF_CAN_ID_HPP
|
||||
#define STA_INTF_CAN_ID_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
/**
|
||||
* @defgroup canID Frame IDs
|
||||
* @ingroup canAPI
|
||||
* @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.
|
||||
*
|
||||
* @ingroup canID
|
||||
*/
|
||||
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) */
|
||||
};
|
||||
|
||||
|
||||
// Comparison operators
|
||||
//
|
||||
|
||||
bool operator ==(const CanId & lhs, const CanId & rhs);
|
||||
bool operator !=(const CanId & lhs, const CanId & rhs);
|
||||
|
||||
bool operator ==(const CanFrameId & lhs, const CanFrameId & rhs);
|
||||
bool operator !=(const CanFrameId & lhs, const CanFrameId & rhs);
|
||||
} // namespace sta
|
||||
|
||||
|
||||
/**
|
||||
* @brief Maximum CAN standard ID value.
|
||||
*
|
||||
* @ingroup canID
|
||||
*/
|
||||
#define CAN_SID_MAX UINT32_C(0x7FF)
|
||||
/**
|
||||
* @brief Maximum CAN extended ID value.
|
||||
*
|
||||
* @ingroup canID
|
||||
*/
|
||||
#define CAN_EID_MAX UINT32_C(0x3FFFF)
|
||||
|
||||
|
||||
#endif // STA_INTF_CAN_ID_HPP
|
104
include/sta/intf/can/subscribable.hpp
Normal file
104
include/sta/intf/can/subscribable.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Subscription interface for CAN controller drivers.
|
||||
*/
|
||||
#ifndef STA_INTF_CAN_SUBSCRIBABLE_HPP
|
||||
#define STA_INTF_CAN_SUBSCRIBABLE_HPP
|
||||
|
||||
#include <sta/intf/can/filter.hpp>
|
||||
#include <sta/intf/can/headers.hpp>
|
||||
|
||||
|
||||
namespace sta
|
||||
{
|
||||
/**
|
||||
* @defgroup canSub Subscription
|
||||
* @ingroup canAPI
|
||||
* @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 Filter configuration and message handler.
|
||||
*
|
||||
* @ingroup canSub
|
||||
*/
|
||||
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;
|
||||
|
||||
// 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 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 Read message from RX FIFO and notify subscriber.
|
||||
*/
|
||||
void receiveAndNotify(uint8_t fifo);
|
||||
|
||||
/**
|
||||
* @brief Process pending frames from RX FIFOs.
|
||||
*/
|
||||
void processMessages();
|
||||
|
||||
|
||||
private:
|
||||
CanRxCallback filterCallbacks_[T::MAX_FILTER_COUNT]; /**< Callbacks for RX filters */
|
||||
};
|
||||
} // namespace sta
|
||||
|
||||
|
||||
#include <sta/intf/can/subscribable.tpp>
|
||||
|
||||
|
||||
#endif // STA_INTF_CAN_SUBSCRIBABLE_HPP
|
120
include/sta/intf/can/subscribable.tpp
Normal file
120
include/sta/intf/can/subscribable.tpp
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @brief Implementation of template class CanController<T>.
|
||||
*/
|
||||
#ifndef STA_INTF_CAN_SUBSCRIBABLE_TPP
|
||||
#define STA_INTF_CAN_SUBSCRIBABLE_TPP
|
||||
|
||||
#ifndef STA_INTF_CAN_SUBSCRIBABLE_HPP
|
||||
#error "Direct use of internal header. Use <sta/intf/can/subscribable.hpp> instead"
|
||||
#endif // !STA_INTF_CAN_SUBSCRIBABLE_HPP
|
||||
|
||||
#ifndef STA_STDLIB_DISABLE
|
||||
# include <algorithm> // fill_n
|
||||
#endif // !STA_STDLIB_DISABLE
|
||||
|
||||
|
||||
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;
|
||||
|
||||
// Clear previous subscriptions
|
||||
unsubscribeAll();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SubscribableCanController<T>::subscribeAll(CanRxCallback callback, uint8_t fifo)
|
||||
{
|
||||
uint8_t filterIdx = 0;
|
||||
|
||||
// Clear previous subscriptions
|
||||
unsubscribeAll();
|
||||
|
||||
// Setup default filter
|
||||
CanFilter filter{};
|
||||
filter.type = CanFilterIdFormat::ANY;
|
||||
filter.fifo = fifo;
|
||||
|
||||
// Store callback
|
||||
filterCallbacks_[filterIdx] = callback;
|
||||
|
||||
// Configure and enable default filter
|
||||
T::configureFilter(filterIdx, filter, true);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SubscribableCanController<T>::unsubscribeAll()
|
||||
{
|
||||
// Disable all filters
|
||||
T::clearFilters();
|
||||
|
||||
// Clear filter callbacks
|
||||
#ifndef STA_STDLIB_DISABLE
|
||||
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;
|
||||
}
|
||||
#endif // STA_STDLIB_DISABLE
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace sta
|
||||
|
||||
|
||||
#endif // STA_INTF_CAN_SUBSCRIBABLE_TPP
|
26
src/can/id.cpp
Normal file
26
src/can/id.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <sta/intf/can/id.hpp>
|
||||
|
||||
|
||||
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 == 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 == rhs);
|
||||
}
|
||||
} // namespace sta
|
Loading…
x
Reference in New Issue
Block a user