canadensis icon indicating copy to clipboard operation
canadensis copied to clipboard

CAN loopback frames

Open chemicstry opened this issue 2 years ago • 4 comments

The library works great, however, I would like to use time synchronisation over canbus. The time synchronisation master requires loopback frames to know the precise transmission timestamp of its messages, but they don't seem to be implemented in canadensis. I would gladly make a PR, but I'm not sure what would be the best way to approach this.

The simlest solution without modifying canadensis internals would be to loopback everything as regular received messages and then check if source id matches current node id in TransferHandler::handle_message. But I'm not sure if this is the best approach, because it could cause weird bugs in other handlers if source id is not checked. It would also act weird in case of a node id conflict.

Another solution would be to add loopback flag to frames (maybe in Transfer and also in canadensis_can::Frame) and then have an additional TransferHandler::handle_loopback(&mut self, node: &mut N, transfer: &Transfer) method. This is similar to how pycyphal does. This way loopback frames can be separated and don't interfere with regular frames.

Any thoughts?

chemicstry avatar Jun 10 '22 12:06 chemicstry

Adding a loopback flag sounds like a good idea.

The only problem I can think of is that some CAN controllers (bxCAN, MCP2515, maybe others) have loopback mode as a global switch and can't loopback specific frames only. The best solution might be documentation saying that some drivers may ignore the loopback flag.

Out of curiosity, what CAN controller are you using that can do loopback for specific frames?

samcrow avatar Jun 10 '22 18:06 samcrow

I'm using bxCAN and it supports loopback only in debug mode (RX is disconnected). However, I'm aiming for a similar implementation as in the old libuavcan, where loopback is implemented in software and TX timestamp is captured in TX mailbox empty interrupt. This is not ideal, but if critical sections in software are short, you can get microsecond precision time synchronisation.

chemicstry avatar Jun 10 '22 19:06 chemicstry

It is reasonable to enable loopback in the driver for all frames and then silently drop all loopback frames except those few that were requested by the application to be reported back. It was implemented this way in the original libuavcan driver for SocketCAN, for example.

pavel-kirienko avatar Jun 10 '22 19:06 pavel-kirienko

Now that I understand the idea of using the interrupt to get a timestamp and do software loopback, this makes more sense. The driver part (canadensis_bxcan or similar) might be slightly challenging, but the rest of the changes seem simple.

samcrow avatar Jun 10 '22 22:06 samcrow