zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.87k stars 6.62k forks source link

MCUBoot with CAN as transport layer #72987

Open vChavezB opened 5 months ago

vChavezB commented 5 months ago

Is your feature request related to a problem? Please describe.

I have a device that I am changing to Zephyr OS. I am building a bootloader but the only transport layer available for production devices is CAN. Unfortunately Mcuboot for zephyr only supports a Serial interface (i.e. CONFIG_MCUBOOT_SERIAL=y)

Describe the solution you'd like

An additional transport layer for CAN. This could be based on the serial transport layer.

Describe alternatives you've considered

I have built my own fork and added the proposed solution

https://github.com/zephyrproject-rtos/mcuboot/compare/main...vChavezB:mcuboot:can

I have not made a PR as I would like to know if there is interest in having such approach. I basically copied the serial transport and changed the API to use CAN instead.

Additional context

Altough there is currently no SMP client that supports CAN, I made a prototype with the awesome project in https://github.com/intercreate/smpmgr. So I was wondering if there is interest in adding CAN as a transport layer for MCUboot.

henrikbrixandersen commented 5 months ago

There are several higher-layer CAN protocols supporting firmware upgrade already, but no standardized low-level CAN protocol for this.

Zephyr already supports firmware upgrade via CANopen (utilizing CANopenNode for the protocol implementation).

Since CAN is a bus consisting of many nodes (as opposed to the point-to-point mcumgr serial connection) I'd say a CAN-based firmware upgrade protocol would need follow a more standardized approach to make it into upstream Zephyr.

faxe1008 commented 5 months ago

I'd be interested in a CAN based recovery mechanism inside of mcuboot. Currently working on a device which uses a proprietary CANOpen stack for the dfu. Issue is that the device only supports the UPGRADE_ONLY mode. From what I see in this PR there is no generic mechanism inside of mcuboot to add a recovery mechanism out of tree, right?

vChavezB commented 5 months ago

Zephyr already supports firmware upgrade via CANopen (utilizing CANopenNode for the protocol implementation).

I checked the docs and as I understand this is based on the Draft Specification Proposal CiA 302-3, which is implemented here .

Is there an open-source/free CANOpen node master (implementation) that can be used to send the updates to the CANOpen node (i.e., zephyr device). For example using a computer and a utility that implements the other part of the CiA 302-3.

My motivation on this feature request is to reuse the features from mcuboot. Does Cia 302-3 have similar features? In addition, I would like to keep the updates only available in the bootloader such as the serial recovery that the mcuboot zephyr port offers.

Since CAN is a bus consisting of many nodes (as opposed to the point-to-point mcumgr serial connection)

Well for my use case I just need to update the devices when they are not operational (i.e., not connected to a can bus). Which would make my connection point-to-point. Hence that is the reason I adopted an approach with MCUBoot and the serial recovery.

vChavezB commented 5 months ago

from what I see in this PR there is no generic mechanism inside of mcuboot to add a recovery mechanism out of tree, right?

That is right @faxe1008 . The recovery mechanism of mcuboot for zephyr is tied to the serial recovery implementation. That is the reason I reused it and changed the physical transport layer to CAN.

If you are interested I also implemented the smpmgr CAN transport here. Its not that fancy... but hey it worked, now I can update my devices over CAN in mcuboot.

henrikbrixandersen commented 5 months ago

Is there an open-source/free CANOpen node master (implementation) that can be used to send the updates to the CANOpen node (i.e., zephyr device). For example using a computer and a utility that implements the other part of the CiA 302-3.

Yes, see e.g. https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/west_commands/runners/canopen_program.py

nordicjm commented 5 months ago

Seems like a nice addition to MCUboot, I would welcome such a PR, though the actual CAN parts of it are something I have no knowledge about. Simulator tests would be ideal if possible. Note that MCUboot coding style is not the same as zephyr's, it is 4 space indent not tab (and the common Kconfig options for serial and CAN can be moved to a separate file and included rather than being duplicated)

vChavezB commented 5 months ago

Thanks for the feedback @nordicjm .

Simulator tests would be ideal if possible.

Is there a particular way to simulate CAN in zephyr?

nordicjm commented 5 months ago

It would be MCUboot simulation testing, there is a whole rust-based simulator which runs in CI - see https://github.com/mcu-tools/mcuboot/tree/main/sim