Summary of the Issue:
Hello! I’m working on building a custom sensor node that operates with CyphalCAN. I’m using a Teensy 4.1 microcontroller for this purpose. I’m developing it using Arduino libraries within the platformIO environment.
Code Snippet:
c++Copy code
#include <FlexCAN_T4.h>
#include <Arduino.h>
#include <107-Arduino-Cyphal.h>
// #include <107-Arduino-Cyphal-Support.h>
// #include <107-Arduino-littlefs.h>
// #include <EEPROM.h>
#define NUM_TX_MAILBOXES 2
#define NUM_RX_MAILBOXES 6
// static littlefs::Filesystem filesystem(filesystem_config);
// cyphal::support::platform::storage::littlefs::KeyValueStorage kv_storage(filesystem);
FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> port_;
void onReceive(const CAN_message_t &rec);
uavcan::node::ExecuteCommand::Response_1_1 onExecuteCommand_1_1_Request_Received(uavcan::node::ExecuteCommand::Request_1_1 const &req);
void can_setup()
{
port_.begin();
port_.setBaudRate(1000000);
port_.setClock(CLK_60MHz);
port_.setMaxMB(NUM_TX_MAILBOXES + NUM_RX_MAILBOXES);
for (int i = 0; i < NUM_RX_MAILBOXES; i++)
{
port_.setMB((FLEXCAN_MAILBOX)i, RX, EXT);
}
for (int i = NUM_RX_MAILBOXES; i < (NUM_TX_MAILBOXES + NUM_RX_MAILBOXES); i++)
{
port_.setMB((FLEXCAN_MAILBOX)i, TX, EXT);
}
port_.setMBFilter(REJECT_ALL);
port_.enableMBInterrupts();
port_.onReceive(MB0, onReceive);
}
void can_setFilter(CanardFilter filter)
{
port_.setMBUserFilter(MB0, filter.extended_can_id, filter.extended_mask);
port_.mailboxStatus();
}
void can_loop()
{
port_.events();
}
CAN_message_t convert(CanardFrame const &frame)
{
CAN_message_t ret;
ret.flags.extended = true;
ret.id = frame.extended_can_id;
ret.len = frame.payload_size;
std::memcpy(ret.buf, frame.payload, frame.payload_size);
// Serial.write((std::to_string(frame.payload_size) + "\r\n").c_str());
return ret;
}
CanardFrame convert(const CAN_message_t &frame)
{
CanardFrame ret;
ret.extended_can_id = frame.id;
ret.payload_size = frame.len;
std::memcpy(ret.payload, frame.buf, frame.len);
return ret;
}
bool can_write(CanardFrame const &frame)
{
port_.write(convert(frame));
return true;
}
CanardPortID port_id_ = 0x40;
CanardNodeID node_id_ = 0x44;
static cyphal::Node::Heap<cyphal::Node::DEFAULT_O1HEAP_SIZE> node_heap_;
static cyphal::Node node_(node_heap_.data(), node_heap_.size(), micros, [](CanardFrame const &frame)
{ return can_write(frame); });
cyphal::Publisher<uavcan::node::Heartbeat_1_0> heartbeat_pub_ = node_.create_publisher<uavcan::node::Heartbeat_1_0>(1 * 1000 * 1000UL);
cyphal::Publisher<uavcan::si::unit::angle::Scalar_1_0> data_pub_ = cyphal::Publisher<uavcan::si::unit::angle::Scalar_1_0>(node_.create_publisher<uavcan::si::unit::angle::Scalar_1_0>(port_id_, 1 * 1000 * 1000UL));
cyphal::ServiceServer execute_command_srv_ = node_.create_service_server<uavcan::node::ExecuteCommand::Request_1_1, uavcan::node::ExecuteCommand::Response_1_1>(2 * 1000 * 1000UL, onExecuteCommand_1_1_Request_Received);
uint64_t prev_heartbeat_{};
uint64_t prev_data_{};
auto registry_ = node_.create_registry();
const auto node_id_ptr = registry_->expose("cyphal.node.id", {true}, node_id_);
const auto node_desp_ptr = registry_->route("cyphal.node.description", {true}, []()
{ return "GYRO Sensor"; });
const auto pub_id_ptr = registry_->expose("cyphal.pub.data_pub_.id", {true}, port_id_);
const auto pub_type_ptr = registry_->route("cyphal.pub.data_pub_.type", {true}, []()
{ return "uavcan.si.unit.angle.Scalar.1.0"; });
void node_setup()
{
node_.setNodeId(node_id_);
static const cyphal::NodeInfo node_info_ = (node_.create_node_info(1, 0, 1, 0, 0, 1, 0, std::array<uint8_t, 16>{1}, "node_name"));
can_setup();
CanardFilter const CAN_FILTER_SERVICES = canardMakeFilterForServices(node_id_);
can_setFilter(CAN_FILTER_SERVICES);
Serial.write("SensorNode\r\n");
}
void node_loop()
{
can_loop();
node_.spinSome();
unsigned long const now = millis();
if ((now - prev_heartbeat_) > 1000)
{
prev_heartbeat_ = now;
uavcan::node::Heartbeat_1_0 msg;
msg.uptime = millis() / 1000;
msg.health.value = uavcan::node::Health_1_0::NOMINAL;
msg.mode.value = uavcan::node::Mode_1_0::OPERATIONAL;
msg.vendor_specific_status_code = 0;
(*heartbeat_pub_).publish(msg);
}
if ((now - prev_data_) > 100)
{
prev_data_ = now;
uavcan::si::unit::angle::Scalar_1_0 msg;
msg.radian = 0.5;
(*data_pub_).publish(msg);
}
}
CanardFrame frame;
void onReceive(const CAN_message_t &rec)
{
Serial.write("onRceive");
frame = convert(rec);
node_.onCanFrameReceived(frame);
Serial.write("onRceive");
}
uavcan::node::ExecuteCommand::Response_1_1 onExecuteCommand_1_1_Request_Received(uavcan::node::ExecuteCommand::Request_1_1 const &req)
{
uavcan::node::ExecuteCommand::Response_1_1 rsp;
rsp.status = uavcan::node::ExecuteCommand::Response_1_1::STATUS_SUCCESS;
Serial.write("Service");
return rsp;
};
void setup()
{
Serial.begin(115200);
delay(500);
Serial.write("Start");
node_setup();
}
void loop()
{
node_loop();
}
Problem Description:
I’ve been attempting to verify if the cyphal Node is functioning on Yukon. However, when I attempted to check this by inserting node_.onCanFrameReceived(frame);
within the onReceive
function, the entire microcontroller crashes.
When running only the publisher without the sensor node receiving any CAN messages or being connected to Yukon, I didn’t encounter any issues with the microcontroller crashing.