Platform-specific components

So I decided to move platform-specific code away from the Libcanard repository, as was planned since long ago. I cast my gaze upon our GitHub organization and saw much clutter. Of the 22 repositories, 5 are dedicated to the platform-specific components of Libuavcan. If we are to continue the same policy with Libcanard, the number of hardware-specific items would be unwieldy. Ideally, I would like to avoid maintaining low-level hardware-specific code completely, and yet here we are.

Having dedicated repositories for each combination of platform+library won’t do so we need a grouping policy. How about we keep one repository per target platform? That might allow us to share platform-specific logic between library-specific components, and, most importantly, that might simplify testing since it would be sufficient to set up the HITL hardware or a simulator once and reuse it.

The other obvious alternative is to move platform-specific parts back with their libraries but it is worse than what we have now because 1. our libraries are platform-agnostic and 2. we can’t maintain every platform-specific component to the same quality standard as the library core.

If the per-platform grouping policy is implemented, we’d end up with the following repositories:

  • stm32 for the Libuavcan and Libcanard platform adapters. Later it will be expanded with a new adapter for STM32H7’s CAN FD macrocell.
  • nxp_s32k for @noxuz’s Libuavcan adapter.
  • nxp_kinetis
  • nxp_lpc11c24 (come to think of it, we have a great deal of NXP in here)
  • nuttx – for Libcanard’s generic NuttX interface (actually I’m thinking we don’t need it at all because it is trivial).
  • socketcan – ideally, this one should be compatible with every flavor of SocketCAN: GNU/Linux, Zephyr, and the upcoming NuttX.


Let me get back to you on this.

One thing I was thinking about that is relevant: what if we created a unified media layer that both libcanard and libuavcan could use (libuavcan would simply create a C++ wrapper to bind to the shared C API)?

Ugh. I would like to keep it simple. I think if there’s a possibility to reuse some functionality, it can be done per-media-layer.

Here is a relevant copy-pasta from Libcanard’s README:

+---------------+                               +---------------------------------------------+
|  Application  |                               |                  Application                |
+-------+-------+                               +-------+---------------------------------+---+
        |                                               | Libcanard does NOT interact     |
+-------+-------+                                       | with the platform drivers       |
|   Libuavcan   |                                       | directly. This interface is     |
+-------+-------+                                       | application-/driver-specific.   |
        | The interface between the             +-------+-------+                 +-------+-------+
        | library and the platform              |    Platform   |                 |   Libcanard   |
        | is defined by the library.            |    drivers    |                 +---------------+
+-------+-------+                               +---------------+
|    Platform   |
|    drivers    |

So after spending some time drinking coffee with my foot (apparently) I’m wondering what we gain from having any separation in repositories? I’m not suggesting that there’s no benefit I’m just not sure what it is. For example, do we think we want different access controls based on the platform grouping? Github/git doesn’t give you much else between repos and if you don’t need the more granular access control why not just have a single platform-specific repo with folders?

That would be a monorepo, right? What I don’t get about monorepos is what benefit is there in having the change history of unrelated entities merged into one stream of commits? But maybe if we implemented one I would finally get an empirical answer to that question. In general I am not against having one large dump repository for all platform-specific things that people could scavenge to look for things they can reuse for their platforms.


Should we do that right now?

No, okay; so the other requirement is discreet commit history. That’s a valid requirement. So how about less granularity then? FlexCAN, MCAN, SocketCAN perhaps? Or by system architecture: bare-metal, linux/SocketCAN, etc?

What I ignored my previous post is that history can be filtered per-directory (or per-file, obviously); even GitHub supports that; for example

The other thing I don’t understand about monorepositories is that they seem to reduce the encapsulation of possibly unrelated codebases. At any rate, I think the cost of a mistake in this particular case is low as long as we don’t push platform-specific things into the same repository with our implementation libraries.

Eh. Can one construct a reusable driver for, say, FlexCAN that could be equally well used on i.MX6 and Kinetis?

My .02€ is to just start with a single repo and be happy if we have the problem of too many chip vendors trying to contribute at once. In that beautiful world we could revisit. Just start with a clear README and a well defined folder structure.

Okay. I am going to rename libuavcan_stm32 into platform_specific_components, move all other things in there, and archive the other repositories.