mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-09 05:08:52 +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)
|
||||
, sysclock_(sysclock)
|
||||
, outgoing_transfer_reg_(otr)
|
||||
, self_node_id_(NodeID::Broadcast) // Default
|
||||
, self_node_id_is_set_(false)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
{
|
||||
UAVCAN_ASSERT((transfer_type == TransferTypeMessageBroadcast) == dst_node_id.isBroadcast());
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class UAVCAN_EXPORT TransferSender
|
||||
const TransferCRC crc_base_;
|
||||
CanIOFlags flags_;
|
||||
uint8_t iface_mask_;
|
||||
bool allow_broadcasting_in_passive_mode_;
|
||||
|
||||
Dispatcher& dispatcher_;
|
||||
|
||||
@@ -46,6 +47,7 @@ public:
|
||||
, crc_base_(data_type.getSignature().toTransferCRC())
|
||||
, flags_(CanIOFlags(0))
|
||||
, iface_mask_(AllIfacesMask)
|
||||
, allow_broadcasting_in_passive_mode_(false)
|
||||
, dispatcher_(dispatcher)
|
||||
{ }
|
||||
|
||||
@@ -59,6 +61,13 @@ public:
|
||||
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.
|
||||
* 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 =
|
||||
(frame_index_ > MaxIndex) ||
|
||||
((frame_index_ == MaxIndex) && !last_frame_) ||
|
||||
(!src_node_id_.isUnicast()) ||
|
||||
(!src_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_ >= NumTransferTypes) ||
|
||||
(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,
|
||||
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())
|
||||
{
|
||||
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();
|
||||
|
||||
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
|
||||
{
|
||||
const int res = frame.setPayload(payload, payload_len);
|
||||
|
||||
@@ -162,7 +162,18 @@ TEST(Frame, FrameParsing)
|
||||
|
||||
can.id = CanFrame::FlagEFF | // cppcheck-suppress duplicateExpression
|
||||
(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};
|
||||
|
||||
// By default, sending in passive mode is not enabled
|
||||
ASSERT_EQ(-uavcan::ErrPassiveMode,
|
||||
sender.send(Payload, sizeof(Payload), tsMono(1000), uavcan::MonotonicTime(),
|
||||
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().getTxTransferCount());
|
||||
EXPECT_EQ(1, dispatcher.getTransferPerfCounter().getTxTransferCount());
|
||||
EXPECT_EQ(0, dispatcher.getTransferPerfCounter().getRxTransferCount());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user