mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-25 06:23:34 +08:00
SocketCAN driver: Fixed frame reordering
This commit is contained in:
@@ -43,10 +43,14 @@ enum class SocketCanError
|
|||||||
* no more than 'max_frames_in_socket_tx_queue_' TX frames, rest is waiting in the user space TX queue; when the
|
* no more than 'max_frames_in_socket_tx_queue_' TX frames, rest is waiting in the user space TX queue; when the
|
||||||
* socket produces loopback for the previously sent TX frame the next frame from the user space TX queue will
|
* socket produces loopback for the previously sent TX frame the next frame from the user space TX queue will
|
||||||
* be sent into the socket.
|
* be sent into the socket.
|
||||||
|
*
|
||||||
* This approach allows to properly maintain TX timeouts (http://stackoverflow.com/questions/19633015/).
|
* This approach allows to properly maintain TX timeouts (http://stackoverflow.com/questions/19633015/).
|
||||||
* TX timestamping is implemented by means of reading RX timestamps of loopback frames (see "TX timestamping" on
|
* TX timestamping is implemented by means of reading RX timestamps of loopback frames (see "TX timestamping" on
|
||||||
* linux-can mailing list, http://permalink.gmane.org/gmane.linux.can/5322).
|
* linux-can mailing list, http://permalink.gmane.org/gmane.linux.can/5322).
|
||||||
*
|
*
|
||||||
|
* Note that if max_frames_in_socket_tx_queue_ is greater than one, frame reordering may occur (depending on the
|
||||||
|
* unrderlying logic).
|
||||||
|
*
|
||||||
* This class is too complex and needs to be refactored later. At least, basic socket IO and configuration
|
* This class is too complex and needs to be refactored later. At least, basic socket IO and configuration
|
||||||
* should be extracted into a different class.
|
* should be extracted into a different class.
|
||||||
*/
|
*/
|
||||||
@@ -93,19 +97,29 @@ class SocketCanIface : public uavcan::ICanIface
|
|||||||
{
|
{
|
||||||
uavcan::CanFrame frame;
|
uavcan::CanFrame frame;
|
||||||
uavcan::MonotonicTime deadline;
|
uavcan::MonotonicTime deadline;
|
||||||
uavcan::CanIOFlags flags;
|
uavcan::CanIOFlags flags = 0;
|
||||||
|
std::uint64_t order = 0;
|
||||||
|
|
||||||
TxItem()
|
TxItem(const uavcan::CanFrame& arg_frame, uavcan::MonotonicTime arg_deadline,
|
||||||
: flags(0)
|
uavcan::CanIOFlags arg_flags, std::uint64_t arg_order)
|
||||||
{ }
|
|
||||||
|
|
||||||
TxItem(const uavcan::CanFrame& arg_frame, uavcan::MonotonicTime arg_deadline, uavcan::CanIOFlags arg_flags)
|
|
||||||
: frame(arg_frame)
|
: frame(arg_frame)
|
||||||
, deadline(arg_deadline)
|
, deadline(arg_deadline)
|
||||||
, flags(arg_flags)
|
, flags(arg_flags)
|
||||||
|
, order(arg_order)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool operator<(const TxItem& rhs) const { return frame.priorityLowerThan(rhs.frame); }
|
bool operator<(const TxItem& rhs) const
|
||||||
|
{
|
||||||
|
if (frame.priorityLowerThan(rhs.frame))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (frame.priorityHigherThan(rhs.frame))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return order > rhs.order;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RxItem
|
struct RxItem
|
||||||
@@ -124,7 +138,9 @@ class SocketCanIface : public uavcan::ICanIface
|
|||||||
const int fd_;
|
const int fd_;
|
||||||
|
|
||||||
const unsigned max_frames_in_socket_tx_queue_;
|
const unsigned max_frames_in_socket_tx_queue_;
|
||||||
unsigned frames_in_socket_tx_queue_;
|
unsigned frames_in_socket_tx_queue_ = 0;
|
||||||
|
|
||||||
|
std::uint64_t tx_frame_counter_ = 0; ///< Increments with every frame pushed into the TX queue
|
||||||
|
|
||||||
std::map<SocketCanError, std::uint64_t> errors_;
|
std::map<SocketCanError, std::uint64_t> errors_;
|
||||||
|
|
||||||
@@ -302,12 +318,13 @@ class SocketCanIface : public uavcan::ICanIface
|
|||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Takes ownership of socket's file descriptor.
|
* Takes ownership of socket's file descriptor.
|
||||||
|
*
|
||||||
|
* @ref max_frames_in_socket_tx_queue See a note in the class comment.
|
||||||
*/
|
*/
|
||||||
SocketCanIface(const SystemClock& clock, int socket_fd, int max_frames_in_socket_tx_queue = 3)
|
SocketCanIface(const SystemClock& clock, int socket_fd, int max_frames_in_socket_tx_queue = 3)
|
||||||
: clock_(clock)
|
: clock_(clock)
|
||||||
, fd_(socket_fd)
|
, fd_(socket_fd)
|
||||||
, max_frames_in_socket_tx_queue_(max_frames_in_socket_tx_queue)
|
, max_frames_in_socket_tx_queue_(max_frames_in_socket_tx_queue)
|
||||||
, frames_in_socket_tx_queue_(0)
|
|
||||||
{
|
{
|
||||||
assert(fd_ >= 0);
|
assert(fd_ >= 0);
|
||||||
}
|
}
|
||||||
@@ -326,7 +343,8 @@ public:
|
|||||||
std::int16_t send(const uavcan::CanFrame& frame, const uavcan::MonotonicTime tx_deadline,
|
std::int16_t send(const uavcan::CanFrame& frame, const uavcan::MonotonicTime tx_deadline,
|
||||||
const uavcan::CanIOFlags flags) override
|
const uavcan::CanIOFlags flags) override
|
||||||
{
|
{
|
||||||
tx_queue_.emplace(frame, tx_deadline, flags);
|
tx_queue_.emplace(frame, tx_deadline, flags, tx_frame_counter_);
|
||||||
|
tx_frame_counter_++;
|
||||||
pollRead(); // Read poll is necessary because it can release the pending TX flag
|
pollRead(); // Read poll is necessary because it can release the pending TX flag
|
||||||
pollWrite();
|
pollWrite();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -509,7 +527,7 @@ private:
|
|||||||
const SystemClock& clock_;
|
const SystemClock& clock_;
|
||||||
uavcan::LazyConstructor<SocketCanIface> ifaces_[MaxIfaces];
|
uavcan::LazyConstructor<SocketCanIface> ifaces_[MaxIfaces];
|
||||||
::pollfd pollfds_[MaxIfaces];
|
::pollfd pollfds_[MaxIfaces];
|
||||||
std::uint8_t num_ifaces_;
|
std::uint8_t num_ifaces_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -517,7 +535,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
explicit SocketCanDriver(const SystemClock& clock)
|
explicit SocketCanDriver(const SystemClock& clock)
|
||||||
: clock_(clock)
|
: clock_(clock)
|
||||||
, num_ifaces_(0)
|
|
||||||
{
|
{
|
||||||
for (auto& p : pollfds_)
|
for (auto& p : pollfds_)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user