You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
240 lines
6.2 KiB
240 lines
6.2 KiB
|
|
#pragma once |
|
|
|
#include <AP_HAL/AP_HAL.h> |
|
|
|
#if AP_UAVCAN_SLCAN_ENABLED |
|
|
|
#include <AP_UAVCAN/AP_UAVCAN.h> |
|
#include "AP_HAL/utility/RingBuffer.h" |
|
|
|
|
|
#define SLCAN_BUFFER_SIZE 200 |
|
#define SLCAN_RX_QUEUE_SIZE 64 |
|
#define SLCAN_DRIVER_INDEX 2 |
|
|
|
class SLCANRouter; |
|
|
|
namespace SLCAN { |
|
/** |
|
* Driver error codes. |
|
* These values can be returned from driver functions negated. |
|
*/ |
|
static const int16_t ErrUnknown = 1000; ///< Reserved for future use |
|
static const int16_t ErrNotImplemented = 1001; ///< Feature not implemented |
|
static const int16_t ErrInvalidBitRate = 1002; ///< Bit rate not supported |
|
static const int16_t ErrLogic = 1003; ///< Internal logic error |
|
static const int16_t ErrUnsupportedFrame = 1004; ///< Frame not supported (e.g. RTR, CAN FD, etc) |
|
static const int16_t ErrMsrInakNotSet = 1005; ///< INAK bit of the MSR register is not 1 |
|
static const int16_t ErrMsrInakNotCleared = 1006; ///< INAK bit of the MSR register is not 0 |
|
static const int16_t ErrBitRateNotDetected = 1007; ///< Auto bit rate detection could not be finished |
|
static const int16_t ErrFilterNumConfigs = 1008; ///< Auto bit rate detection could not be finished |
|
class CANManager; |
|
/** |
|
* RX queue item. |
|
* The application shall not use this directly. |
|
*/ |
|
struct CanRxItem { |
|
uint64_t utc_usec; |
|
uavcan::CanFrame frame; |
|
uavcan::CanIOFlags flags; |
|
CanRxItem() : |
|
utc_usec(0), flags(0) |
|
{ |
|
} |
|
}; |
|
class CAN: public AP_HAL::CAN { |
|
friend class CANManager; |
|
friend class ::SLCANRouter; |
|
struct TxItem { |
|
uavcan::MonotonicTime deadline; |
|
uavcan::CanFrame frame; |
|
|
|
bool pending; |
|
|
|
bool loopback; |
|
|
|
bool abort_on_error; |
|
|
|
TxItem() : |
|
pending(false), loopback(false), abort_on_error(false) |
|
{ |
|
} |
|
}; |
|
|
|
enum { |
|
NumTxMailboxes = 3 |
|
}; |
|
enum { |
|
NumFilters = 14 |
|
}; |
|
|
|
uint32_t bitrate_; |
|
|
|
virtual int16_t send(const uavcan::CanFrame& frame, uavcan::MonotonicTime tx_deadline, |
|
uavcan::CanIOFlags flags) override; |
|
|
|
virtual int16_t receive(uavcan::CanFrame& out_frame, uavcan::MonotonicTime& out_ts_monotonic, |
|
uavcan::UtcTime& out_ts_utc, uavcan::CanIOFlags& out_flags) override; |
|
|
|
int16_t reportFrame(const uavcan::CanFrame& frame, bool loopback, uint64_t timestamp_usec); |
|
|
|
virtual int16_t configureFilters(const uavcan::CanFilterConfig* filter_configs, uint16_t num_configs) override |
|
{ |
|
//TODO: possibly check at the first serial read |
|
return 0; |
|
} |
|
|
|
virtual uint16_t getNumFilters() const override |
|
{ |
|
return NumFilters; |
|
} |
|
|
|
/** |
|
* Total number of hardware failures and other kinds of errors (e.g. queue overruns). |
|
* May increase continuously if the interface is not connected to the bus. |
|
*/ |
|
virtual uint64_t getErrorCount() const override |
|
{ |
|
return 0; |
|
} |
|
|
|
const char* processCommand(char* cmd); |
|
|
|
bool push_Frame(uavcan::CanFrame &frame); |
|
|
|
bool handle_FrameRTRStd(const char* cmd); |
|
bool handle_FrameRTRExt(const char* cmd); |
|
bool handle_FrameDataStd(const char* cmd); |
|
bool handle_FrameDataExt(const char* cmd); |
|
void reader(); |
|
|
|
inline void addByte(const uint8_t byte); |
|
|
|
bool initialized_; |
|
bool _port_initialised; |
|
char buf_[SLCAN_BUFFER_SIZE + 1]; |
|
int16_t pos_ = 0; |
|
AP_HAL::UARTDriver *_port = nullptr; |
|
|
|
ObjectBuffer<CanRxItem> rx_queue_; |
|
uint8_t self_index_; |
|
HAL_Semaphore rx_sem_; |
|
unsigned _pending_frame_size = 0; |
|
|
|
const uint32_t _serial_lock_key = 0x53494442; |
|
bool _close = true; |
|
public: |
|
|
|
CAN(uint8_t self_index, uint8_t rx_queue_capacity): |
|
self_index_(self_index), rx_queue_(rx_queue_capacity), _port_initialised(false) |
|
{ |
|
UAVCAN_ASSERT(self_index_ < CAN_STM32_NUM_IFACES); |
|
} |
|
enum { |
|
MaxRxQueueCapacity = 254 |
|
}; |
|
|
|
enum OperatingMode { |
|
NormalMode, SilentMode |
|
}; |
|
|
|
int init(const uint32_t bitrate, const OperatingMode mode, AP_HAL::UARTDriver* port); |
|
|
|
bool begin(uint32_t bitrate) override |
|
{ |
|
if (init(bitrate, OperatingMode::NormalMode, nullptr) == 0) { |
|
bitrate_ = bitrate; |
|
initialized_ = true; |
|
} |
|
else { |
|
initialized_ = false; |
|
} |
|
return initialized_; |
|
} |
|
|
|
void end() override |
|
{ |
|
} |
|
|
|
void reset() override; |
|
|
|
int32_t tx_pending() override |
|
{ |
|
return _port->tx_pending() ? 0:-1; |
|
} |
|
|
|
int32_t available() override |
|
{ |
|
return _port->available() ? 0:-1; |
|
} |
|
|
|
bool is_initialized() override |
|
{ |
|
return initialized_; |
|
} |
|
bool closed() |
|
{ |
|
return _close; |
|
} |
|
bool pending_frame_sent(); |
|
|
|
bool isRxBufferEmpty(void); |
|
bool canAcceptNewTxFrame() const; |
|
}; |
|
|
|
|
|
class CANManager: public AP_HAL::CANManager, public uavcan::ICanDriver { |
|
bool initialized_; |
|
CAN driver_; |
|
uint8_t _ifaces_num = 1; |
|
|
|
virtual int16_t select(uavcan::CanSelectMasks& inout_masks, |
|
const uavcan::CanFrame* (&pending_tx)[uavcan::MaxCanIfaces], uavcan::MonotonicTime blocking_deadline) override; |
|
|
|
uavcan::CanSelectMasks makeSelectMasks(const uavcan::CanFrame* (&pending_tx)[uavcan::MaxCanIfaces]); |
|
thread_t *_irq_handler_ctx = nullptr; |
|
public: |
|
CANManager() |
|
: AP_HAL::CANManager(this), initialized_(false), driver_(SLCAN_DRIVER_INDEX, SLCAN_RX_QUEUE_SIZE) |
|
{ } |
|
|
|
/** |
|
* Whether at least one iface had at least one successful IO since previous call of this method. |
|
* This is designed for use with iface activity LEDs. |
|
*/ |
|
//bool hadActivity(); |
|
|
|
static CANManager *from(AP_HAL::CANManager *can) |
|
{ |
|
return static_cast<CANManager*>(can); |
|
} |
|
|
|
bool begin(uint32_t bitrate, uint8_t can_number) override; |
|
|
|
/* |
|
Test if CAN manager is ready and initialized |
|
return false - CAN manager not initialized |
|
true - CAN manager is initialized |
|
*/ |
|
bool is_initialized() override; |
|
void initialized(bool val) override; |
|
|
|
virtual CAN* getIface(uint8_t iface_index) override |
|
{ |
|
return &driver_; |
|
} |
|
|
|
virtual uint8_t getNumIfaces() const override |
|
{ |
|
return _ifaces_num; |
|
} |
|
|
|
void reader_trampoline(void); |
|
}; |
|
|
|
} |
|
#include <AP_HAL_ChibiOS/CANSerialRouter.h> |
|
|
|
#endif // AP_UAVCAN_SLCAN_ENABLED |
|
|
|
|