Announcing WIP: Go port of libcanard

Hello there! I’ve been working towards creating a port of libcanard for Go.
It aims to be portable and lightweight like the reference with slightly different API to that of libcanard. Notable differences:

  • Make use of Go’s error type for errors
  • Uses standard library’s memory allocator
  • Use methods to simplify working with data types such as Tail byte, CRC, NodeID, etc.

This project readily compiles with tinygo to over 80 micro-controller targets as well as your favorite OS and architecture.

1 Like

Sounds awesome. Is your work open source? If so, are you planning to share a link to it? I would love to have a look.

One thing that is missing in libcanard by design is the set of higher-level capabilities that used to be provided in the original libuavcan v0, such as high-level pub/sub API, register interface, and so on. We’ve been planning to create a higher-level libcyphal that would be put on top of libcanard, libudpard, and possibly other transport implementations to provide these missing higher-level protocol capabilities and reduce the adoption barriers. This matters because the capabilities offered by libcanard/libudpard are so bare-bones that one has to learn quite a bit of the protocol to get it to work correctly. Hence, I have two questions:

  • Do you have plans to provide higher-level protocol capabilities in your library?
  • Do you intend to support other transports, most importantly Cyphal/UDP?

How could I have missed that! Heres the repo: https://github.com/soypat/go-canard

My plan with go-canard is to have a bare-bones working cyphal implementation so that it can be used with Go. Usage will bring out pain points. It will also help me understand how Cyphal really works. Porting the library has given me a much better understanding than I initially had though I’m still hazy on the details.

To answer your questions:

Do you have plans to provide higher-level protocol capabilities in your library?

No plans. I guess time will tell, maybe using this library as-is is hard enough to warrant a higher-level API. In this case I’d certainly want to have a higher level API. Though since I still have not used this library I have no need for it and so no idea of what shape or form it would have!

Do you intend to support other transports, most importantly Cyphal/UDP?

If I do it’d be conforming to the standard library API implementation of UDP. This is a goal of the library since I do plan on working with UDP with this. Supporting UDP would then also support TCP by extension.

What I like about this implementation is the error handling. One could already used go-canard to build a packet/bus analyzer, if I’m not mistaken.

I think it’s not really about the API of your library but rather about the capabilities implemented. For instance, if I wanted to implement the register interface (a very core capability that is required for basically any node), I would have to write tedious stuff like this:

There are better ways to spend developer’s time.

I guess it makes sense for a Go library. Are UDP sockets supported in Tiny Go though? WIth libudpard the plan is to go low-level, incorporating a minimal UDP/IP stack with IGMP support. Is IGMP supported in Tiny Go?

I don’t think so. Cyphal/UDP and Cyphal/serial do not really have much in common, but I suppose it’s not very important right now.

write tedious stuff like this […] There are better ways to spend developer’s time.

Which leads me to believe: yes, there is a need for a higher level API.

Are UDP sockets supported in Tiny Go though?

Not today. The plan is to implement it someday. I’ve written a few really bad micro Ethernet/IP/TCP stacks back in the day. Plan is to write an actual good one next time.

I don’t think so. Cyphal/UDP and Cyphal/serial do not really have much in common

Hmm. I’m probably misunderstanding something about how the Cyphal works? My thinking is based on how the Go standard library works: the API for TCP and UDP packet sending is nearly identical, minimal modification would be necessary to convert a UDP packet protocol to TCP packet protocol. But that is a ways off, like you say: not of most importance right now.