mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-02 07:21:36 +08:00
TransferSender is now capable of broadcasting in passive mode; Frame::isValid() was modified to accept SFT broadcasts with zero SNID
This commit is contained in:
@@ -115,6 +115,7 @@ public:
|
|||||||
: canio_(driver, allocator, sysclock)
|
: canio_(driver, allocator, sysclock)
|
||||||
, sysclock_(sysclock)
|
, sysclock_(sysclock)
|
||||||
, outgoing_transfer_reg_(otr)
|
, outgoing_transfer_reg_(otr)
|
||||||
|
, self_node_id_(NodeID::Broadcast) // Default
|
||||||
, self_node_id_is_set_(false)
|
, self_node_id_is_set_(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public:
|
|||||||
{
|
{
|
||||||
UAVCAN_ASSERT((transfer_type == TransferTypeMessageBroadcast) == dst_node_id.isBroadcast());
|
UAVCAN_ASSERT((transfer_type == TransferTypeMessageBroadcast) == dst_node_id.isBroadcast());
|
||||||
UAVCAN_ASSERT(data_type_id.isValid());
|
UAVCAN_ASSERT(data_type_id.isValid());
|
||||||
UAVCAN_ASSERT(src_node_id != dst_node_id);
|
UAVCAN_ASSERT(src_node_id.isUnicast() ? (src_node_id != dst_node_id) : true);
|
||||||
UAVCAN_ASSERT(frame_index <= MaxIndex);
|
UAVCAN_ASSERT(frame_index <= MaxIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class UAVCAN_EXPORT TransferSender
|
|||||||
const TransferCRC crc_base_;
|
const TransferCRC crc_base_;
|
||||||
CanIOFlags flags_;
|
CanIOFlags flags_;
|
||||||
uint8_t iface_mask_;
|
uint8_t iface_mask_;
|
||||||
|
bool allow_broadcasting_in_passive_mode_;
|
||||||
|
|
||||||
Dispatcher& dispatcher_;
|
Dispatcher& dispatcher_;
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ public:
|
|||||||
, crc_base_(data_type.getSignature().toTransferCRC())
|
, crc_base_(data_type.getSignature().toTransferCRC())
|
||||||
, flags_(CanIOFlags(0))
|
, flags_(CanIOFlags(0))
|
||||||
, iface_mask_(AllIfacesMask)
|
, iface_mask_(AllIfacesMask)
|
||||||
|
, allow_broadcasting_in_passive_mode_(false)
|
||||||
, dispatcher_(dispatcher)
|
, dispatcher_(dispatcher)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -59,6 +61,13 @@ public:
|
|||||||
iface_mask_ = iface_mask;
|
iface_mask_ = iface_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, this class will return an error on any attempt to publish a message while the
|
||||||
|
* dispatcher is configured in passive mode. This method allows to permanently enable sending
|
||||||
|
* broadcast transfers in passive mode for this class instance.
|
||||||
|
*/
|
||||||
|
void allowBroadcastingInPassiveMode() { allow_broadcasting_in_passive_mode_ = true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send with explicit Transfer ID.
|
* Send with explicit Transfer ID.
|
||||||
* Should be used only for service responses, where response TID should match request TID.
|
* Should be used only for service responses, where response TID should match request TID.
|
||||||
|
|||||||
@@ -170,9 +170,12 @@ bool Frame::isValid() const
|
|||||||
const bool invalid =
|
const bool invalid =
|
||||||
(frame_index_ > MaxIndex) ||
|
(frame_index_ > MaxIndex) ||
|
||||||
((frame_index_ == MaxIndex) && !last_frame_) ||
|
((frame_index_ == MaxIndex) && !last_frame_) ||
|
||||||
(!src_node_id_.isUnicast()) ||
|
(!src_node_id_.isValid()) ||
|
||||||
(!dst_node_id_.isValid()) ||
|
(!dst_node_id_.isValid()) ||
|
||||||
(src_node_id_ == dst_node_id_) ||
|
(src_node_id_.isUnicast() ? (src_node_id_ == dst_node_id_) : false) ||
|
||||||
|
(src_node_id_.isBroadcast()
|
||||||
|
? (!last_frame_ || (frame_index_ > 0) || (transfer_type_ != TransferTypeMessageBroadcast))
|
||||||
|
: false) ||
|
||||||
((transfer_type_ == TransferTypeMessageBroadcast) != dst_node_id_.isBroadcast()) ||
|
((transfer_type_ == TransferTypeMessageBroadcast) != dst_node_id_.isBroadcast()) ||
|
||||||
(transfer_type_ >= NumTransferTypes) ||
|
(transfer_type_ >= NumTransferTypes) ||
|
||||||
(static_cast<int>(payload_len_) > getMaxPayloadLen()) ||
|
(static_cast<int>(payload_len_) > getMaxPayloadLen()) ||
|
||||||
|
|||||||
@@ -19,15 +19,37 @@ int TransferSender::send(const uint8_t* payload, unsigned payload_len, Monotonic
|
|||||||
MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id,
|
MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id,
|
||||||
TransferID tid)
|
TransferID tid)
|
||||||
{
|
{
|
||||||
|
if (payload_len > MaxTransferPayloadLen)
|
||||||
|
{
|
||||||
|
UAVCAN_ASSERT(0);
|
||||||
|
return -ErrInvalidParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame frame(data_type_.getID(), transfer_type, dispatcher_.getNodeID(), dst_node_id, 0, tid);
|
||||||
|
UAVCAN_TRACE("TransferSender", "%s", frame.toString().c_str());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checking if we're allowed to send. In passive mode we can send only if:
|
||||||
|
* - Passive broadcasting is enabled
|
||||||
|
* - Transfer type is broadcast
|
||||||
|
* - Transfer payload fits one CAN frame
|
||||||
|
*/
|
||||||
if (dispatcher_.isPassiveMode())
|
if (dispatcher_.isPassiveMode())
|
||||||
{
|
{
|
||||||
return -ErrPassiveMode;
|
const bool allow = allow_broadcasting_in_passive_mode_ &&
|
||||||
|
(transfer_type == TransferTypeMessageBroadcast) &&
|
||||||
|
(int(payload_len) <= frame.getMaxPayloadLen());
|
||||||
|
if (!allow)
|
||||||
|
{
|
||||||
|
return -ErrPassiveMode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatcher_.getTransferPerfCounter().addTxTransfer();
|
dispatcher_.getTransferPerfCounter().addTxTransfer();
|
||||||
|
|
||||||
Frame frame(data_type_.getID(), transfer_type, dispatcher_.getNodeID(), dst_node_id, 0, tid);
|
/*
|
||||||
|
* Sending frames
|
||||||
|
*/
|
||||||
if (frame.getMaxPayloadLen() >= int(payload_len)) // Single Frame Transfer
|
if (frame.getMaxPayloadLen() >= int(payload_len)) // Single Frame Transfer
|
||||||
{
|
{
|
||||||
const int res = frame.setPayload(payload, payload_len);
|
const int res = frame.setPayload(payload, payload_len);
|
||||||
|
|||||||
@@ -162,7 +162,18 @@ TEST(Frame, FrameParsing)
|
|||||||
|
|
||||||
can.id = CanFrame::FlagEFF | // cppcheck-suppress duplicateExpression
|
can.id = CanFrame::FlagEFF | // cppcheck-suppress duplicateExpression
|
||||||
(2 << 0) | (1 << 3) | (0 << 4) | (0 << 10) | (uavcan::TransferTypeMessageUnicast << 17) | (456 << 19);
|
(2 << 0) | (1 << 3) | (0 << 4) | (0 << 10) | (uavcan::TransferTypeMessageUnicast << 17) | (456 << 19);
|
||||||
ASSERT_FALSE(frame.parse(can)); // Broadcast Src Node ID
|
ASSERT_FALSE(frame.parse(can)); // Broadcast Src Node ID with unicast transfer
|
||||||
|
|
||||||
|
can.id = CanFrame::FlagEFF | // cppcheck-suppress duplicateExpression
|
||||||
|
(2 << 0) | (0 << 3) | (0 << 4) | (0 << 10) | (uavcan::TransferTypeMessageBroadcast << 17) | (456 << 19);
|
||||||
|
ASSERT_FALSE(frame.parse(can)); // Broadcast Src Node ID with multiframe broadcast transfer
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Broadcast SNID exceptions
|
||||||
|
*/
|
||||||
|
can.id = CanFrame::FlagEFF | // cppcheck-suppress duplicateExpression
|
||||||
|
(2 << 0) | (1 << 3) | (0 << 4) | (0 << 10) | (uavcan::TransferTypeMessageBroadcast << 17) | (456 << 19);
|
||||||
|
ASSERT_TRUE(frame.parse(can)); // Broadcast Src Node ID with single frame broadcast transfer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -235,11 +235,24 @@ TEST(TransferSender, PassiveMode)
|
|||||||
|
|
||||||
static const uint8_t Payload[] = {1, 2, 3, 4, 5};
|
static const uint8_t Payload[] = {1, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
// By default, sending in passive mode is not enabled
|
||||||
ASSERT_EQ(-uavcan::ErrPassiveMode,
|
ASSERT_EQ(-uavcan::ErrPassiveMode,
|
||||||
sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
|
sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
|
||||||
uavcan::TransferTypeMessageBroadcast, uavcan::NodeID::Broadcast));
|
uavcan::TransferTypeMessageBroadcast, uavcan::NodeID::Broadcast));
|
||||||
|
|
||||||
|
// Overriding the default
|
||||||
|
sender.allowBroadcastingInPassiveMode();
|
||||||
|
|
||||||
|
// OK, now we can broadcast in any mode
|
||||||
|
ASSERT_LE(0, sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
|
||||||
|
uavcan::TransferTypeMessageBroadcast, uavcan::NodeID::Broadcast));
|
||||||
|
|
||||||
|
// ...but not unicast or anything else
|
||||||
|
ASSERT_EQ(-uavcan::ErrPassiveMode,
|
||||||
|
sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
|
||||||
|
uavcan::TransferTypeMessageUnicast, uavcan::NodeID(42)));
|
||||||
|
|
||||||
EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getErrorCount());
|
EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getErrorCount());
|
||||||
EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getTxTransferCount());
|
EXPECT_EQ(1, dispatcher.getTransferPerfCounter().getTxTransferCount());
|
||||||
EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getRxTransferCount());
|
EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getRxTransferCount());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user