uc_transfer_receiver.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
7 #include <uavcan/debug.hpp>
8 #include <cstdlib>
9 #include <cassert>
10 
11 namespace uavcan
12 {
13 
18 
20 {
22 }
23 
25 {
27 }
28 
30 {
31  error_cnt_ = static_cast<uint8_t>(error_cnt_ + 1) & ErrorCntMask;
32 }
33 
35 {
37 
38  const MonotonicTime prev_prev_ts = prev_transfer_ts_;
40 
41  if ((!prev_prev_ts.isZero()) && (!prev_transfer_ts_.isZero()) && (prev_transfer_ts_ >= prev_prev_ts))
42  {
43  uint64_t interval_msec = uint64_t((prev_transfer_ts_ - prev_prev_ts).toMSec());
44  interval_msec = min(interval_msec, uint64_t(MaxTransferIntervalMSec));
45  interval_msec = max(interval_msec, uint64_t(MinTransferIntervalMSec));
46  transfer_interval_msec_ = static_cast<uint16_t>((uint64_t(transfer_interval_msec_) * 7U + interval_msec) / 8U);
47  }
48 }
49 
51 {
52  tid_.increment();
53  next_toggle_ = false;
55 }
56 
58 {
59  if (iface_index_ != frame.getIfaceIndex())
60  {
61  return false;
62  }
63  if (frame.isStartOfTransfer() && !frame.isEndOfTransfer() && (frame.getPayloadLen() < TransferCRC::NumBytes))
64  {
65  UAVCAN_TRACE("TransferReceiver", "CRC expected, %s", frame.toString().c_str());
66  registerError();
67  return false;
68  }
69  if (frame.isStartOfTransfer() && frame.getToggle())
70  {
71  UAVCAN_TRACE("TransferReceiver", "Toggle bit is not cleared, %s", frame.toString().c_str());
72  registerError();
73  return false;
74  }
75  if (frame.isStartOfTransfer() && isMidTransfer())
76  {
77  UAVCAN_TRACE("TransferReceiver", "Unexpected start of transfer, %s", frame.toString().c_str());
78  registerError();
79  }
80  if (frame.getToggle() != next_toggle_)
81  {
82  UAVCAN_TRACE("TransferReceiver", "Unexpected toggle bit (not %i), %s",
83  int(next_toggle_), frame.toString().c_str());
84  registerError();
85  return false;
86  }
87  if (frame.getTransferID() != tid_)
88  {
89  UAVCAN_TRACE("TransferReceiver", "Unexpected TID (current %i), %s", tid_.get(), frame.toString().c_str());
90  registerError();
91  return false;
92  }
93  return true;
94 }
95 
97 {
98  const uint8_t* const payload = frame.getPayloadPtr();
99  const unsigned payload_len = frame.getPayloadLen();
100 
101  if (frame.isStartOfTransfer()) // First frame contains CRC, we need to extract it now
102  {
103  if (frame.getPayloadLen() < TransferCRC::NumBytes)
104  {
105  return false; // Must have been validated earlier though. I think I'm paranoid.
106  }
107  this_transfer_crc_ = static_cast<uint16_t>(payload[0] & 0xFF);
108  this_transfer_crc_ |= static_cast<uint16_t>(static_cast<uint16_t>(payload[1] & 0xFF) << 8); // Little endian.
109 
110  const unsigned effective_payload_len = payload_len - TransferCRC::NumBytes;
111  const int res = buf.write(buffer_write_pos_, payload + TransferCRC::NumBytes, effective_payload_len);
112  const bool success = res == static_cast<int>(effective_payload_len);
113  if (success)
114  {
115  buffer_write_pos_ = static_cast<uint16_t>(buffer_write_pos_ + effective_payload_len);
116  }
117  return success;
118  }
119  else
120  {
121  const int res = buf.write(buffer_write_pos_, payload, payload_len);
122  const bool success = res == static_cast<int>(payload_len);
123  if (success)
124  {
125  buffer_write_pos_ = static_cast<uint16_t>(buffer_write_pos_ + payload_len);
126  }
127  return success;
128  }
129 }
130 
132 {
133  // Transfer timestamps are derived from the first frame
134  if (frame.isStartOfTransfer())
135  {
136  this_transfer_ts_ = frame.getMonotonicTimestamp();
137  first_frame_ts_ = frame.getUtcTimestamp();
138  }
139 
140  if (frame.isStartOfTransfer() && frame.isEndOfTransfer())
141  {
142  tba.remove();
145  this_transfer_crc_ = 0; // SFT has no CRC
146  return ResultSingleFrame;
147  }
148 
149  // Payload write
150  ITransferBuffer* buf = tba.access();
151  if (buf == UAVCAN_NULLPTR)
152  {
153  buf = tba.create();
154  }
155  if (buf == UAVCAN_NULLPTR)
156  {
157  UAVCAN_TRACE("TransferReceiver", "Failed to access the buffer, %s", frame.toString().c_str());
159  registerError();
160  return ResultNotComplete;
161  }
162  if (!writePayload(frame, *buf))
163  {
164  UAVCAN_TRACE("TransferReceiver", "Payload write failed, %s", frame.toString().c_str());
165  tba.remove();
167  registerError();
168  return ResultNotComplete;
169  }
171 
172  if (frame.isEndOfTransfer())
173  {
176  return ResultComplete;
177  }
178  return ResultNotComplete;
179 }
180 
182 {
183  return (current_ts - this_transfer_ts_) > getTidTimeout();
184 }
185 
187 {
188  if ((frame.getMonotonicTimestamp().isZero()) ||
189  (frame.getMonotonicTimestamp() < prev_transfer_ts_) ||
190  (frame.getMonotonicTimestamp() < this_transfer_ts_))
191  {
192  UAVCAN_TRACE("TransferReceiver", "Invalid frame, %s", frame.toString().c_str());
193  return ResultNotComplete;
194  }
195 
196  const bool not_initialized = !isInitialized();
197  const bool tid_timed_out = isTimedOut(frame.getMonotonicTimestamp());
198  const bool same_iface = frame.getIfaceIndex() == iface_index_;
199  const bool first_frame = frame.isStartOfTransfer();
200  const bool non_wrapped_tid = tid_.computeForwardDistance(frame.getTransferID()) < TransferID::Half;
201  const bool not_previous_tid = frame.getTransferID().computeForwardDistance(tid_) > 1;
202  const bool iface_switch_allowed = (frame.getMonotonicTimestamp() - this_transfer_ts_) > getIfaceSwitchDelay();
203 
204  // FSM, the hard way
205  const bool need_restart =
206  (not_initialized) ||
207  (tid_timed_out) ||
208  (same_iface && first_frame && not_previous_tid) ||
209  (iface_switch_allowed && first_frame && non_wrapped_tid);
210 
211  if (need_restart)
212  {
213  if (!not_initialized && (tid_ != frame.getTransferID()))
214  {
215  registerError();
216  }
217  UAVCAN_TRACE("TransferReceiver", "Restart [ni=%d, isa=%d, tt=%d, si=%d, ff=%d, nwtid=%d, nptid=%d, tid=%d], %s",
218  int(not_initialized), int(iface_switch_allowed), int(tid_timed_out), int(same_iface),
219  int(first_frame), int(non_wrapped_tid), int(not_previous_tid), int(tid_.get()),
220  frame.toString().c_str());
221  tba.remove();
222  iface_index_ = frame.getIfaceIndex() & IfaceIndexMask;
223  tid_ = frame.getTransferID();
224  next_toggle_ = false;
225  buffer_write_pos_ = 0;
226  this_transfer_crc_ = 0;
227  if (!first_frame)
228  {
229  tid_.increment();
230  return ResultNotComplete;
231  }
232  }
233 
234  if (!validate(frame))
235  {
236  return ResultNotComplete;
237  }
238  return receive(frame, tba);
239 }
240 
242 {
243  const uint8_t ret = error_cnt_;
244  error_cnt_ = 0;
245  return ret;
246 }
247 
248 }
uavcan::TransferReceiver::prev_transfer_ts_
MonotonicTime prev_transfer_ts_
Definition: transfer_receiver.hpp:39
uavcan::TransferBufferAccessor::create
ITransferBuffer * create()
Definition: transfer_buffer.hpp:193
uavcan::TransferBufferAccessor::access
ITransferBuffer * access()
Definition: transfer_buffer.hpp:192
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::uint64_t
std::uint64_t uint64_t
Definition: std.hpp:27
uavcan::TransferReceiver::this_transfer_ts_
MonotonicTime this_transfer_ts_
Definition: transfer_receiver.hpp:40
debug.hpp
uavcan::TransferReceiver::error_cnt_
uint8_t error_cnt_
Definition: transfer_receiver.hpp:52
crc.hpp
uavcan::TransferReceiver::isMidTransfer
bool isMidTransfer() const
Definition: transfer_receiver.hpp:56
uavcan::TransferReceiver::MaxTransferIntervalMSec
static const uint16_t MaxTransferIntervalMSec
Definition: transfer_receiver.hpp:22
uavcan::TransferReceiver::writePayload
bool writePayload(const RxFrame &frame, ITransferBuffer &buf)
Definition: uc_transfer_receiver.cpp:96
uavcan::ITransferBuffer
Definition: abstract_transfer_buffer.hpp:16
uavcan::TransferReceiver::getIfaceSwitchDelay
MonotonicDuration getIfaceSwitchDelay() const
Definition: uc_transfer_receiver.cpp:19
uavcan::TransferReceiver::IfaceIndexMask
@ IfaceIndexMask
Definition: transfer_receiver.hpp:37
uavcan::DurationBase< MonotonicDuration >::fromMSec
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
uavcan::TransferReceiver::DefaultTransferIntervalMSec
static const uint16_t DefaultTransferIntervalMSec
Definition: transfer_receiver.hpp:23
uavcan::TransferReceiver::receive
ResultCode receive(const RxFrame &frame, TransferBufferAccessor &tba)
Definition: uc_transfer_receiver.cpp:131
uavcan::TransferReceiver::ErrorCntMask
@ ErrorCntMask
Definition: transfer_receiver.hpp:36
uavcan::TransferReceiver::prepareForNextTransfer
void prepareForNextTransfer()
Definition: uc_transfer_receiver.cpp:50
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::TransferReceiver::yieldErrorCount
uint8_t yieldErrorCount()
Definition: uc_transfer_receiver.cpp:241
uavcan::TransferBufferAccessor
Definition: transfer_buffer.hpp:180
uavcan::MonotonicDuration
Definition: time.hpp:182
uavcan::TransferReceiver::addFrame
ResultCode addFrame(const RxFrame &frame, TransferBufferAccessor &tba)
Definition: uc_transfer_receiver.cpp:186
uavcan::TransferReceiver::ResultSingleFrame
@ ResultSingleFrame
Definition: transfer_receiver.hpp:19
uavcan::TransferID::get
uint8_t get() const
Definition: transfer.hpp:99
uavcan::TransferReceiver::validate
bool validate(const RxFrame &frame) const
Definition: uc_transfer_receiver.cpp:57
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::RxFrame
Definition: frame.hpp:104
uavcan::TransferID::computeForwardDistance
int computeForwardDistance(TransferID rhs) const
Definition: uc_transfer.cpp:44
uavcan::TransferReceiver::registerError
void registerError() const
Definition: uc_transfer_receiver.cpp:29
uavcan::max
const UAVCAN_EXPORT T & max(const T &a, const T &b)
Definition: templates.hpp:291
uavcan::TransferID::Half
static const uint8_t Half
Definition: transfer.hpp:78
uavcan::TransferReceiver::first_frame_ts_
UtcTime first_frame_ts_
Definition: transfer_receiver.hpp:41
uavcan::TransferReceiver::ResultNotComplete
@ ResultNotComplete
Definition: transfer_receiver.hpp:19
uavcan::ITransferBuffer::write
virtual int write(unsigned offset, const uint8_t *data, unsigned len)=0
uavcan::TransferCRC::NumBytes
@ NumBytes
Definition: crc.hpp:37
uavcan::TransferReceiver::getTidTimeout
MonotonicDuration getTidTimeout() const
Definition: uc_transfer_receiver.cpp:24
uavcan::TransferReceiver::tid_
TransferID tid_
Definition: transfer_receiver.hpp:47
uavcan::TransferReceiver::iface_index_
uint8_t iface_index_
Definition: transfer_receiver.hpp:51
uavcan::TransferReceiver::next_toggle_
uint8_t next_toggle_
Definition: transfer_receiver.hpp:50
uavcan::TransferReceiver::ResultCode
ResultCode
Definition: transfer_receiver.hpp:19
uavcan::TimeBase::isZero
bool isZero() const
Definition: time.hpp:123
uavcan::min
const UAVCAN_EXPORT T & min(const T &a, const T &b)
Definition: templates.hpp:281
uavcan::TransferReceiver::buffer_write_pos_
uint16_t buffer_write_pos_
Definition: transfer_receiver.hpp:45
frame
uavcan::CanFrame frame
Definition: can.cpp:78
uavcan::TransferReceiver::updateTransferTimings
void updateTransferTimings()
Definition: uc_transfer_receiver.cpp:34
uavcan::TransferReceiver::this_transfer_crc_
uint16_t this_transfer_crc_
Definition: transfer_receiver.hpp:43
uavcan::TransferReceiver::isInitialized
bool isInitialized() const
Definition: transfer_receiver.hpp:54
uavcan::TransferReceiver::transfer_interval_msec_
uint16_t transfer_interval_msec_
Definition: transfer_receiver.hpp:42
uavcan::MonotonicTime
Definition: time.hpp:184
uavcan::TransferReceiver::DefaultTidTimeoutMSec
static const uint16_t DefaultTidTimeoutMSec
Definition: transfer_receiver.hpp:24
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
transfer_receiver.hpp
uavcan::TransferReceiver::isTimedOut
bool isTimedOut(MonotonicTime current_ts) const
Definition: uc_transfer_receiver.cpp:181
uavcan::TransferID::increment
void increment()
Definition: transfer.hpp:94
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::TransferReceiver::MinTransferIntervalMSec
static const uint16_t MinTransferIntervalMSec
Definition: transfer_receiver.hpp:21
uavcan::TransferBufferAccessor::remove
void remove()
Definition: transfer_buffer.hpp:194
uavcan::TransferReceiver::ResultComplete
@ ResultComplete
Definition: transfer_receiver.hpp:19


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