Deserialization of Vector31_0_1 fails in ISR routine on ESP32
I would like to start by clarifying that this is not an issue with code written in this repository. It actually is an issue with the nunavut-generated headers in this repo and how they are used on an ESP32 using the https://github.com/adafruit/arduino-CAN library. However, since this repository includes the generated headers and is listed as supporting the ESP32, I believe this issue needs to be mentioned in the readme for users that may experience the same difficulty as I. My explanation is below.
Situation: Following the example in https://forum.uavcan.org/t/107-arduino-uavcan-with-esp32/1096 for receiving CAN messages on an ESP32, I wrote a sketch that subscribes to the reg::drone::service::actuator::common::sp::Vector31_0_1<PORT_ID> message. This message is used by PX4 uavcan_v1 for sending setpoints to ESCs. The example on which I based my sketch uses an ISR to deserialize the message and handle the deserialized message. When my sketch received the Vector31_0_1 message and attempted to deserialize it in the ISR, it resulted in a "Guru Meditation Error: Core 1 panic'ed (Coprocessor exception)" with subsequent reboot.
Analysis: Per research through online forums, the ESP32 does not allow floating point arithmetic in ISRs by default. Apparently an experimental option to handle floating point arithmetic can be enabled in the ESP-IDF, but that does not help us in the Arduino toolchain. Line 476 of 107-Arduino-UAVCAN/src/nunavut/support/serialization.h is out.real *= magic.real;, which is floating point arithmetic. That line is causing the error and reboot.
Solutions: (1) Use the ESP-IDF and enable the experimental option to allow floating point arithmetic in ISRs. As noted above, this is not a useful option since this software seems targeted towards the Arduino toolchain. (2) Change line 466 of serialization.h from "real real;" to "double real;" and line 482 of serialization.h from "return out.real;" to "return (float)out.real;" This method forces double arithmetic in the ISR, which is handled in software, not in the floating point coprocessor, so does not trip the Guru error. (3) Do not deserialize any of the Vector messages (all of them exhibit this issue) in an ISR on an ESP32. Instead, copy the memory to a buffer and deserialize outside the ISR. This method had potential issues with synchronization between ISRs and executing processes, so there is another set of issues to deal with here.
I chose option (2), and that option is working correctly. I can deserialize the messages and use the data without issues.
Again, this issue is only present on the ESP32, only present on messages that require floating point arithmetic in deserialization, and only present if using a design patter that uses ISRs to receive the messages. Because it is a very niche situation and involves the integration of several repos, I do not know if there is necessarily a good code fix for this issue, but it should be something of which developers are made aware. Since this repo includes the generated headers and is listed as supporting the ESP32 (which has a CAN controller so does not require the MCP2515 or similar), it seemed like this repo was a reasonable central point to make developers aware of this issue to see if there is a good way to handle this.
Please let me know if you need more information. I can attach a minimal sketch if that would help.