uc_transfer_sender.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
6 #include <uavcan/debug.hpp>
7 #include <cassert>
8 
9 
10 namespace uavcan
11 {
12 
14 {
16 }
17 
19 {
21 
22  data_type_id_ = dtid.getID();
24 }
25 
26 int TransferSender::send(const uint8_t* payload, unsigned payload_len, MonotonicTime tx_deadline,
27  MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id,
28  TransferID tid) const
29 {
30  Frame frame(data_type_id_, transfer_type, dispatcher_.getNodeID(), dst_node_id, tid);
31 
32  frame.setPriority(priority_);
33  frame.setStartOfTransfer(true);
34 
35  UAVCAN_TRACE("TransferSender", "%s", frame.toString().c_str());
36 
37  /*
38  * Checking if we're allowed to send.
39  * In passive mode we can send only anonymous transfers, if they are enabled.
40  */
42  {
43  const bool allow = allow_anonymous_transfers_ &&
44  (transfer_type == TransferTypeMessageBroadcast) &&
45  (int(payload_len) <= frame.getPayloadCapacity());
46  if (!allow)
47  {
48  return -ErrPassiveMode;
49  }
50  }
51 
53 
54  /*
55  * Sending frames
56  */
57  if (frame.getPayloadCapacity() >= payload_len) // Single Frame Transfer
58  {
59  const int res = frame.setPayload(payload, payload_len);
60  if (res != int(payload_len))
61  {
62  UAVCAN_ASSERT(0);
63  UAVCAN_TRACE("TransferSender", "Frame payload write failure, %i", res);
64  registerError();
65  return (res < 0) ? res : -ErrLogic;
66  }
67 
68  frame.setEndOfTransfer(true);
69  UAVCAN_ASSERT(frame.isStartOfTransfer() && frame.isEndOfTransfer() && !frame.getToggle());
70 
71  const CanIOFlags flags = frame.getSrcNodeID().isUnicast() ? flags_ : (flags_ | CanIOFlagAbortOnError);
72 
73  return dispatcher_.send(frame, tx_deadline, blocking_deadline, flags, iface_mask_);
74  }
75  else // Multi Frame Transfer
76  {
78  UAVCAN_ASSERT(frame.getSrcNodeID().isUnicast());
79 
80  int offset = 0;
81  {
82  TransferCRC crc = crc_base_;
83  crc.add(payload, payload_len);
84 
85  static const int BUFLEN = sizeof(static_cast<CanFrame*>(0)->data);
86  uint8_t buf[BUFLEN];
87 
88  buf[0] = uint8_t(crc.get() & 0xFFU); // Transfer CRC, little endian
89  buf[1] = uint8_t((crc.get() >> 8) & 0xFF);
90  (void)copy(payload, payload + BUFLEN - 2, buf + 2);
91 
92  const int write_res = frame.setPayload(buf, BUFLEN);
93  if (write_res < 2)
94  {
95  UAVCAN_TRACE("TransferSender", "Frame payload write failure, %i", write_res);
96  registerError();
97  return write_res;
98  }
99  offset = write_res - 2;
100  UAVCAN_ASSERT(int(payload_len) > offset);
101  }
102 
103  int num_sent = 0;
104 
105  while (true)
106  {
107  const int send_res = dispatcher_.send(frame, tx_deadline, blocking_deadline, flags_, iface_mask_);
108  if (send_res < 0)
109  {
110  registerError();
111  return send_res;
112  }
113 
114  num_sent++;
115  if (frame.isEndOfTransfer())
116  {
117  return num_sent; // Number of frames transmitted
118  }
119 
120  frame.setStartOfTransfer(false);
121  frame.flipToggle();
122 
123  UAVCAN_ASSERT(offset >= 0);
124  const int write_res = frame.setPayload(payload + offset, payload_len - unsigned(offset));
125  if (write_res < 0)
126  {
127  UAVCAN_TRACE("TransferSender", "Frame payload write failure, %i", write_res);
128  registerError();
129  return write_res;
130  }
131 
132  offset += write_res;
133  UAVCAN_ASSERT(offset <= int(payload_len));
134  if (offset >= int(payload_len))
135  {
136  frame.setEndOfTransfer(true);
137  }
138  }
139  }
140 
141  UAVCAN_ASSERT(0);
142  return -ErrLogic; // Return path analysis is apparently broken. There should be no warning, this 'return' is unreachable.
143 }
144 
145 int TransferSender::send(const uint8_t* payload, unsigned payload_len, MonotonicTime tx_deadline,
146  MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id) const
147 {
148  /*
149  * TODO: TID is not needed for anonymous transfers, this part of the code can be skipped?
150  */
151  const OutgoingTransferRegistryKey otr_key(data_type_id_, transfer_type, dst_node_id);
152 
153  UAVCAN_ASSERT(!tx_deadline.isZero());
154  const MonotonicTime otr_deadline = tx_deadline + max(max_transfer_interval_ * 2,
156 
157  TransferID* const tid = dispatcher_.getOutgoingTransferRegistry().accessOrCreate(otr_key, otr_deadline);
158  if (tid == UAVCAN_NULLPTR)
159  {
160  UAVCAN_TRACE("TransferSender", "OTR access failure, dtid=%d tt=%i",
161  int(data_type_id_.get()), int(transfer_type));
162  return -ErrMemory;
163  }
164 
165  const TransferID this_tid = tid->get();
166  tid->increment();
167 
168  return send(payload, payload_len, tx_deadline, blocking_deadline, transfer_type,
169  dst_node_id, this_tid);
170 }
171 
172 }
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
debug.hpp
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::TransferType
TransferType
Definition: transfer.hpp:18
uavcan::OutgoingTransferRegistryKey
Definition: outgoing_transfer_registry.hpp:19
uavcan::TransferSender::crc_base_
TransferCRC crc_base_
Definition: transfer_sender.hpp:27
uavcan::TransferCRC::add
void add(uint8_t byte)
Definition: crc.hpp:60
uavcan::DataTypeSignature::toTransferCRC
TransferCRC toTransferCRC() const
Definition: uc_data_type.cpp:85
uavcan::CanFrame
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:24
transfer_sender.hpp
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::OutgoingTransferRegistry::accessOrCreate
TransferID * accessOrCreate(const OutgoingTransferRegistryKey &key, MonotonicTime new_deadline)
Definition: uc_outgoing_transfer_registry.cpp:27
uavcan::TransferID::get
uint8_t get() const
Definition: transfer.hpp:99
uavcan::TransferSender::allow_anonymous_transfers_
bool allow_anonymous_transfers_
Definition: transfer_sender.hpp:31
uavcan::TransferID
Definition: transfer.hpp:71
uavcan_kinetis::ErrLogic
static const uavcan::int16_t ErrLogic
Internal logic error.
Definition: platform_specific_components/kinetis/libuavcan/driver/include/uavcan_kinetis/can.hpp:22
uavcan::TransferPerfCounter::addTxTransfer
void addTxTransfer()
Definition: perf_counter.hpp:49
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::DataTypeDescriptor
Definition: data_type.hpp:130
uavcan::TransferTypeMessageBroadcast
@ TransferTypeMessageBroadcast
Definition: transfer.hpp:22
uavcan::TransferSender::max_transfer_interval_
const MonotonicDuration max_transfer_interval_
Definition: transfer_sender.hpp:22
uavcan::DataTypeID::get
uint16_t get() const
Definition: data_type.hpp:69
uavcan::max
const UAVCAN_EXPORT T & max(const T &a, const T &b)
Definition: templates.hpp:291
uavcan::TransferSender::priority_
TransferPriority priority_
Definition: transfer_sender.hpp:26
uavcan::TimeBase::isZero
bool isZero() const
Definition: time.hpp:123
uavcan::TransferSender::isInitialized
bool isInitialized() const
Definition: transfer_sender.hpp:66
frame
uavcan::CanFrame frame
Definition: can.cpp:78
uavcan::TransferSender::iface_mask_
uint8_t iface_mask_
Definition: transfer_sender.hpp:30
uavcan::TransferPerfCounter::addError
void addError()
Definition: perf_counter.hpp:52
uavcan::TransferSender::flags_
CanIOFlags flags_
Definition: transfer_sender.hpp:29
uavcan::Dispatcher::send
int send(const Frame &frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, CanIOFlags flags, uint8_t iface_mask)
Definition: uc_dispatcher.cpp:287
uavcan::TransferSender::send
int send(const uint8_t *payload, unsigned payload_len, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id, TransferID tid) const
Definition: uc_transfer_sender.cpp:26
uavcan::Frame
Definition: frame.hpp:17
uavcan::TransferSender::init
void init(const DataTypeDescriptor &dtid)
Definition: uc_transfer_sender.cpp:18
uavcan::Dispatcher::getOutgoingTransferRegistry
OutgoingTransferRegistry & getOutgoingTransferRegistry()
Definition: dispatcher.hpp:204
uavcan::Dispatcher::getTransferPerfCounter
const TransferPerfCounter & getTransferPerfCounter() const
Definition: dispatcher.hpp:236
uavcan::Dispatcher::getNodeID
NodeID getNodeID() const
Definition: dispatcher.hpp:222
uavcan::TransferSender::dispatcher_
Dispatcher & dispatcher_
Definition: transfer_sender.hpp:24
uavcan::DataTypeDescriptor::getID
DataTypeID getID() const
Definition: data_type.hpp:159
uavcan::CanIOFlags
uint16_t CanIOFlags
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:140
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::copy
UAVCAN_EXPORT OutputIt copy(InputIt first, InputIt last, OutputIt result)
Definition: templates.hpp:238
uavcan::TransferSender::data_type_id_
DataTypeID data_type_id_
Definition: transfer_sender.hpp:28
uavcan::CanIOFlagAbortOnError
static const CanIOFlags CanIOFlagAbortOnError
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:142
uavcan::DataTypeDescriptor::getSignature
const DataTypeSignature & getSignature() const
Definition: data_type.hpp:160
uavcan::TransferID::increment
void increment()
Definition: transfer.hpp:94
uavcan::TransferCRC
Definition: crc.hpp:28
uavcan::TransferSender::registerError
void registerError() const
Definition: uc_transfer_sender.cpp:13
uavcan::Dispatcher::isPassiveMode
bool isPassiveMode() const
Definition: dispatcher.hpp:228
uavcan::OutgoingTransferRegistry::MinEntryLifetime
static const MonotonicDuration MinEntryLifetime
Definition: outgoing_transfer_registry.hpp:115
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::TransferCRC::get
uint16_t get() const
Definition: crc.hpp:75


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03