SocketCAN and CAN char diver merge
Hello, Recently I've been working on LIN bus support with SAME70 based device. In general the integration was done smoothly and I would like to contribute my work to the community. The LIN is pretty similar to CAN and in Linux is abstracted as a SocketCAN device. During my integration I chose a more traditional character driver "/dev/linX", but with CAN driver interface. Currently I see that "old" CAN character driver and new SocketCAN live in parallel with a decent amount of duplicated definitions that are already out of sync. I see a room for improvement here and want to share my thoughts. I think that it should be possible to adapt CAN lower interface "struct can_ops_s" so that it can be used by both CAN char and CAN netdev devices upper drive logic. Taking into account that upper layer driver may operate with messages of a different structure (might have padding fields, etc) the minimum common logic should be defined as well. I will express what should be done in a list: 1. All CAN char drivers use "cd_priv" field from "struct can_dev_s" while lower driver interface require pointer to "struct can_dev_s" to be passed. Here we need to define an intermediate type "struct can_updev_s" that will have first two members of "cd_ops" and "cd_priv" so "struct can_dev_s" and "struct can_netdev_s" can be inherited from "struct can_updev_s". 2. "co_send" interface in "struct can_ops_s" should be changed from "CODE int (*co_send)(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg);" to "CODE int (*co_send)(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, FAR uint8_t *data);" -- so we can get away from "struct can_msg_s" that is specific to CAN char driver. 3. The CAN upper logic is already decoupled from "struct can_msg_s" because of "int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, FAR uint8_t *data);" already contain separation, so we need just change "struct can_dev_s" to "struct can_updev_s" here and char dev or netdev will register a proper input callback that will handle RX data or a proper input callback can be added into "struct can_updev_s" 4. "struct can_hdr_s" should be reworked so it can have maximum in common with SocketCAN. SocketCAN expects that lower layer can operate either with standard or extended CAN IDs, so SocketCAN will be available only if CONFIG_CAN_EXTID=y a) In case of CONFIG_CAN_EXTID=y the ch_id in "struct can_hdr_s" is uint32_t, so 3 upper bits are unused. SocketCAN stores supplementary information in those 3 bits like "std vs ext CAN-ID", "RTR vs non-RTR request" and "Error bit". I think we can adopt the same approach and eliminate "ch_rtr", "ch_extid" and "ch_error" bit fields from "struct can_hdr_s" with zero memory or performance hit. b) With "ch_dlc" and "ch_edl" / "ch_brs" / "ch_esi" it will be not so easy because SocketCAN defines two uint8_t fields for this "len" and "flags" while char driver packs everything using bit-fields. Here I need an advice. We can keep bit-fields in the header and then split into two uint8_t in the "can_receive()" variant of SocketCAN or we can extend "struct can_hdr_s" to have 2 uint8_t. The second will not give any memory overhead compared to what we have now because existing bit fields occupy exactly 2 uint8_t variables (but using bit-fields will allow us to save 1 byte of course). I would appreciate your feedback if above makes sense. Thank you in advance, Petro
Re: SocketCAN and CAN char diver merge
Hi Petro, I understand having 2 upper separate layers for CAN isn't welcomed. However I don't see any real particular gains for a generic can_ops_s for both the SocketCAN and CAN Char driver. For example SocketCAN net_driver_s interface uses the dev->d_buf interface to transfer data and then invokes a callback to the actual driver. Whereas CAN Char uses the following prototype to call the driver directly int (*co_send)(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg); If we would manage to unify this we would probably have to rewrite the net/can upper driver to facilitate this. Furthermore modifying the CAN Char can_hdr_s and can_msg_s data structure would break backwards compatibility with all applications using the existing CAN char driver. I'm not aware on the usage of the current CAN char driver is in general. Another option instead of breaking the backwards compatibility for the existing systems would be deprecating CAN Char and try to encourage the use of the SocketCAN driver and maybe migrate some platforms over as well. I've made a quick overview of all NuttX architectures implementing a CAN driver using both upper layers. +-+--+---+ | | Char CAN | SocketCAN | +-+--+---+ | AM335X |Yes | No| +-+--+---+ | IXMRT |No|Yes| +-+--+---+ | SAMA5 |Yes | No| +-+--+---+ | SAMV7 |Yes | No| +-+--+---+ | STM32L4 |Yes | No| +-+--+---+ | LPC43 |Yes | No| +-+--+---+ | STM32 |Yes |Yes| +-+--+---+ | Kinetis |No|Yes| +-+--+---+ | S32K1XX |No|Yes| +-+--+---+ | STM32F7 |Yes | No| +-+--+---+ | STM32H7 |No|Yes| +-+--+---+ | STM32L4 |Yes | No| +-+--+---+ | ESP32C3 |Yes | No| +-+--+---+ | | 9/13 |5/13 | +-+--+---+
Re: SocketCAN and CAN char diver merge
The main reason why I'm raising this topic is that I think that the CAN lower part should be a standard way the upper layer talks to CAN HW and the upper half should perform the translation to a char or netdev interface. Now that is not true. Basically I'm looking into the minimal set of functions that I need to implement for LIN without knowing what is "stilling" on top of it. I believe that it should be the right way of doing things. From a user perspective I do not see any reason in deprecation of CAN char driver. I'm not sure how it is done for Linux, I mean is SocketCAN the only interface to CAN bus in Linux? The deprecation of the CAN char driver could probably solve the issue, but I see that there are many good things in CAN char driver that are not fully integrated with SocketCAN in NuttX. Like HW message filtering (that is currently managed by the SW SocketCAN layer). Best regards, Petro вт, 26 квіт. 2022 р. о 00:06 Peter van der Perk пише: > Hi Petro, > > I understand having 2 upper separate layers for CAN isn't welcomed. > However I don't see any real particular gains for a generic can_ops_s > for both the SocketCAN and CAN Char driver. > > For example SocketCAN net_driver_s interface uses the dev->d_buf > interface to transfer data and then invokes a callback to the actual > driver. > Whereas CAN Char uses the following prototype to call the driver directly > int (*co_send)(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg); > If we would manage to unify this we would probably have to rewrite the > net/can upper driver to facilitate this. > > Furthermore modifying the CAN Char can_hdr_s and can_msg_s data > structure would break backwards compatibility with all applications using > the existing CAN char driver. > > I'm not aware on the usage of the current CAN char driver is in general. > Another option instead of breaking the backwards compatibility for the > existing systems would be deprecating CAN Char and try to encourage > the use of the SocketCAN driver and maybe migrate some platforms over as > well. > > I've made a quick overview of all NuttX architectures implementing a CAN > driver using both upper layers. > > +-+--+---+ > | | Char CAN | SocketCAN | > +-+--+---+ > | AM335X |Yes | No| > +-+--+---+ > | IXMRT |No|Yes| > +-+--+---+ > | SAMA5 |Yes | No| > +-+--+---+ > | SAMV7 |Yes | No| > +-+--+---+ > | STM32L4 |Yes | No| > +-+--+---+ > | LPC43 |Yes | No| > +-+--+---+ > | STM32 |Yes |Yes| > +-+--+---+ > | Kinetis |No|Yes| > +-+--+---+ > | S32K1XX |No|Yes| > +-+--+---+ > | STM32F7 |Yes | No| > +-+--+---+ > | STM32H7 |No|Yes| > +-+--+---+ > | STM32L4 |Yes | No| > +-+--+---+ > | ESP32C3 |Yes | No| > +-+--+---+ > | | 9/13 |5/13 | > +-+--+---+ > >
Re: SocketCAN and CAN char diver merge
There is another precedent here: nuttx/wireless/ieee802154. For that radio family, there are 3 applications interfaces: There is a dumb serial driver and a network driver. The network driver supports both a simple raw interface and also an IPv6 LoPAN interface. There is nothing that can be done with the serial driver that cannot be done with the network raw packet interface. IOCTL commands, for example, are handled by the same logic. They are totally redundant. The serial driver is a remnant of an older architectural concept that evolved over time as documented here: https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=139629397 (focuses on WiFI and Bluetooth as well as 802.15.4 radios). I think that same policy on CAN networking should apply here. Architectural consistency is an important property of a well-designed operating system. Removing the IEEE802.15.4 serial driver at this point would be a difficult thing since it is entangled with the i8sak application so intimately. However, I doubt there is such entanglement with the CAN serial driver other than a few examples and perhaps some utilities. So one option would be to replace the CAN serial driver with a network raw socket type. How does Linux deal with the CAN low level interface? My bet would be through a raw socket. Commonality with Linux in at least naming would be a good thing too. On Mon, Apr 25, 2022 at 3:49 PM Petro Karashchenko < petro.karashche...@gmail.com> wrote: > The main reason why I'm raising this topic is that I think that the CAN > lower part should be a standard way the upper layer talks to CAN HW and the > upper half should perform the translation to a char or netdev interface. > Now that is not true. Basically I'm looking into the minimal set of > functions that I need to implement for LIN without knowing what is > "stilling" on top of it. I believe that it should be the right way of doing > things. From a user perspective I do not see any reason in deprecation of > CAN char driver. I'm not sure how it is done for Linux, I mean is SocketCAN > the only interface to CAN bus in Linux? > > The deprecation of the CAN char driver could probably solve the issue, but > I see that there are many good things in CAN char driver that are not fully > integrated with SocketCAN in NuttX. Like HW message filtering (that is > currently managed by the SW SocketCAN layer). > > Best regards, > Petro > > вт, 26 квіт. 2022 р. о 00:06 Peter van der Perk > пише: > > > Hi Petro, > > > > I understand having 2 upper separate layers for CAN isn't welcomed. > > However I don't see any real particular gains for a generic can_ops_s > > for both the SocketCAN and CAN Char driver. > > > > For example SocketCAN net_driver_s interface uses the dev->d_buf > > interface to transfer data and then invokes a callback to the actual > > driver. > > Whereas CAN Char uses the following prototype to call the driver directly > > int (*co_send)(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg); > > If we would manage to unify this we would probably have to rewrite the > > net/can upper driver to facilitate this. > > > > Furthermore modifying the CAN Char can_hdr_s and can_msg_s data > > structure would break backwards compatibility with all applications using > > the existing CAN char driver. > > > > I'm not aware on the usage of the current CAN char driver is in general. > > Another option instead of breaking the backwards compatibility for the > > existing systems would be deprecating CAN Char and try to encourage > > the use of the SocketCAN driver and maybe migrate some platforms over as > > well. > > > > I've made a quick overview of all NuttX architectures implementing a CAN > > driver using both upper layers. > > > > +-+--+---+ > > | | Char CAN | SocketCAN | > > +-+--+---+ > > | AM335X |Yes | No| > > +-+--+---+ > > | IXMRT |No|Yes| > > +-+--+---+ > > | SAMA5 |Yes | No| > > +-+--+---+ > > | SAMV7 |Yes | No| > > +-+--+---+ > > | STM32L4 |Yes | No| > > +-+--+---+ > > | LPC43 |Yes | No| > > +-+--+---+ > > | STM32 |Yes |Yes| > > +-+--+---+ > > | Kinetis |No|Yes| > > +-+--+---+ > > | S32K1XX |No|Yes| > > +-+--+---+ > > | STM32F7 |Yes | No| > > +-+--+---+ > > | STM32H7 |No|Yes| > > +-+--+---+ > > | STM32L4 |Yes | No| > > +-+--+---+ > > | ESP32C3 |Yes | No| > > +-+--+---+ > > | | 9/13 |5/13 | > > +-+--+---+ > > > > >
Is there a standard way to build e.g. a nshlib.a static library from the apps repository?
Hello everybody, I am currently experimenting with buildroot to create a NuttX SDK, which includes a GCC toolchain build using NuttX as the C library and basically a sysroot environment that contains static libraries (for e.g. libwebsockets, sqlite, etc...), which can optionally be linked by users of the SDK into their application images. I would like to include some of the great pieces of software from the apps repository as static libraries in such an SDK. E.g. a nshlib.a or a netlib.a. Is there a 'standard way' of doing this? Sorry if I missed some obvious documentation. As always, thanks for your help! Michael
Re: Is there a standard way to build e.g. a nshlib.a static library from the apps repository?
You may try to overwrite BIN in nshlib/Makefile to libnsh.a. On Tue, Apr 26, 2022 at 2:38 PM Michael Jung wrote: > Hello everybody, > > I am currently experimenting with buildroot to create a NuttX SDK, which > includes a GCC toolchain build using NuttX as the C library and basically a > sysroot environment that contains static libraries (for e.g. libwebsockets, > sqlite, etc...), which can optionally be linked by users of the SDK into > their application images. > > I would like to include some of the great pieces of software from the apps > repository as static libraries in such an SDK. E.g. a nshlib.a or a > netlib.a. Is there a 'standard way' of doing this? Sorry if I missed some > obvious documentation. > > As always, thanks for your help! > Michael >