From c159f9f7dfbee5b9d5d9f9be02bca309849592b0 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Tue, 28 Apr 2015 11:27:01 +0300 Subject: [PATCH] First step in changing the CAN frame format - introduced various transfer lengths per transfer type --- .../data_type_template.tmpl | 2 +- .../uavcan/node/generic_subscriber.hpp | 2 +- .../include/uavcan/node/marshal_buffer.hpp | 2 +- libuavcan/include/uavcan/node/node.hpp | 2 +- .../include/uavcan/transport/transfer.hpp | 31 +++++++++++++++++-- .../src/transport/uc_transfer_sender.cpp | 2 +- .../test/transport/transfer_listener.cpp | 17 +++++----- 7 files changed, 44 insertions(+), 14 deletions(-) diff --git a/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/data_type_template.tmpl b/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/data_type_template.tmpl index 8b3ba7855e..0c98cec956 100644 --- a/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/data_type_template.tmpl +++ b/libuavcan/dsdl_compiler/libuavcan_dsdl_compiler/data_type_template.tmpl @@ -94,7 +94,7 @@ struct UAVCAN_EXPORT ${t.cpp_type_name} % endfor { enum { MaxByteLen = ::uavcan::BitLenToByteLen::Result }; - ::uavcan::StaticAssert::check(); + ::uavcan::StaticAssert::check(); ::uavcan::StaticAssert<_tmpl == 0>::check(); // Usage check diff --git a/libuavcan/include/uavcan/node/generic_subscriber.hpp b/libuavcan/include/uavcan/node/generic_subscriber.hpp index 46a272fdee..8b7ddb320f 100644 --- a/libuavcan/include/uavcan/node/generic_subscriber.hpp +++ b/libuavcan/include/uavcan/node/generic_subscriber.hpp @@ -124,7 +124,7 @@ template ::Result }; - enum { NeedsBuffer = int(DataTypeMaxByteLen) > int(MaxSingleFrameTransferPayloadLen) }; + enum { NeedsBuffer = int(DataTypeMaxByteLen) > int(GuaranteedPayloadLenPerFrame) }; enum { BufferSize = NeedsBuffer ? DataTypeMaxByteLen : 0 }; #if UAVCAN_TINY enum { NumStaticBufs = 0 }; diff --git a/libuavcan/include/uavcan/node/marshal_buffer.hpp b/libuavcan/include/uavcan/node/marshal_buffer.hpp index 7e55ce49dc..35a7e0885a 100644 --- a/libuavcan/include/uavcan/node/marshal_buffer.hpp +++ b/libuavcan/include/uavcan/node/marshal_buffer.hpp @@ -46,7 +46,7 @@ public: * This implementation provides the buffer large enough to * serialize any UAVCAN data structure. */ -template +template class UAVCAN_EXPORT MarshalBufferProvider : public IMarshalBufferProvider { class Buffer : public IMarshalBuffer diff --git a/libuavcan/include/uavcan/node/node.hpp b/libuavcan/include/uavcan/node/node.hpp index a3e88ff829..ad6cfd5b8d 100644 --- a/libuavcan/include/uavcan/node/node.hpp +++ b/libuavcan/include/uavcan/node/node.hpp @@ -60,7 +60,7 @@ template class UAVCAN_EXPORT Node : public INode diff --git a/libuavcan/include/uavcan/transport/transfer.hpp b/libuavcan/include/uavcan/transport/transfer.hpp index 50255fe37c..6ffcd19175 100644 --- a/libuavcan/include/uavcan/transport/transfer.hpp +++ b/libuavcan/include/uavcan/transport/transfer.hpp @@ -11,10 +11,16 @@ namespace uavcan { +/** + * Refer to the UAVCAN specification for more info about transfers. + */ +static const unsigned MaxMessageBroadcastTransferPayloadLen = 126; ///< 16 frames, 8 bytes per frame, 2 byte CRC +static const unsigned MaxMessageUnicastTransferPayloadLen = 110; ///< 16 frames, 7 bytes per frame, 2 byte CRC +static const unsigned MaxServiceTransferPayloadLen = 439; ///< 63 frames, 7 bytes per frame, 2 byte CRC -static const unsigned MaxTransferPayloadLen = 439; ///< According to the specification. +static const unsigned GuaranteedPayloadLenPerFrame = 7; ///< Guaranteed for all transfers, all CAN standards -static const unsigned MaxSingleFrameTransferPayloadLen = 7; +static const unsigned MaxPossibleTransferPayloadLen = MaxServiceTransferPayloadLen; enum TransferType { @@ -26,6 +32,27 @@ enum TransferType }; +static inline unsigned getMaxPayloadLenForTransferType(const TransferType type) +{ + static const unsigned lens[NumTransferTypes] = + { + MaxServiceTransferPayloadLen, + MaxServiceTransferPayloadLen, + MaxMessageBroadcastTransferPayloadLen, + MaxMessageUnicastTransferPayloadLen + }; + if (static_cast(type) < NumTransferTypes) + { + return lens[static_cast(type)]; + } + else + { + UAVCAN_ASSERT(0); + return 0; + } +} + + class UAVCAN_EXPORT TransferID { uint8_t value_; diff --git a/libuavcan/src/transport/uc_transfer_sender.cpp b/libuavcan/src/transport/uc_transfer_sender.cpp index 0e603a4b54..31315073c2 100644 --- a/libuavcan/src/transport/uc_transfer_sender.cpp +++ b/libuavcan/src/transport/uc_transfer_sender.cpp @@ -19,7 +19,7 @@ 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) + if (payload_len > getMaxPayloadLenForTransferType(transfer_type)) { UAVCAN_ASSERT(0); return -ErrInvalidParam; diff --git a/libuavcan/test/transport/transfer_listener.cpp b/libuavcan/test/transport/transfer_listener.cpp index fd42c1f118..e94499b721 100644 --- a/libuavcan/test/transport/transfer_listener.cpp +++ b/libuavcan/test/transport/transfer_listener.cpp @@ -225,21 +225,24 @@ TEST(TransferListener, MaximumTransferLength) uavcan::PoolManager<1> poolmgr; uavcan::TransferPerfCounter perf; - TestListener subscriber(perf, type, poolmgr); - - static const std::string DATA_OK(uavcan::MaxTransferPayloadLen, 'z'); + TestListener subscriber(perf, type, poolmgr); TransferListenerEmulator emulator(subscriber, type); const Transfer transfers[] = { - emulator.makeTransfer(uavcan::TransferTypeMessageUnicast, 1, DATA_OK), - emulator.makeTransfer(uavcan::TransferTypeMessageBroadcast, 1, DATA_OK) + emulator.makeTransfer(uavcan::TransferTypeServiceRequest, 1, + std::string(uavcan::MaxServiceTransferPayloadLen, 'z')), // Longer + emulator.makeTransfer(uavcan::TransferTypeMessageUnicast, 2, + std::string(uavcan::MaxMessageUnicastTransferPayloadLen, 'z')), // Shorter + emulator.makeTransfer(uavcan::TransferTypeMessageBroadcast, 3, + std::string(uavcan::MaxMessageBroadcastTransferPayloadLen, 'z')) // Same as above }; emulator.send(transfers); - ASSERT_TRUE(subscriber.matchAndPop(transfers[1])); // Broadcast is shorter, so will complete first - ASSERT_TRUE(subscriber.matchAndPop(transfers[0])); + ASSERT_TRUE(subscriber.matchAndPop(transfers[1])); + ASSERT_TRUE(subscriber.matchAndPop(transfers[2])); + ASSERT_TRUE(subscriber.matchAndPop(transfers[0])); // Service takes more frames ASSERT_TRUE(subscriber.isEmpty()); }