-
-
Notifications
You must be signed in to change notification settings - Fork 103
Description
This is a bug report for ArduinoCore-renesas (RA6M5 / Portenta C33 CAN).
Summary
On Arduino Portenta C33 (RA6M5), using CAN0 and CAN1 simultaneously causes a critical issue:
Calling CAN1.write() corrupts the receive FIFO of CAN0.
As a result, CAN0 receives frames that were never sent to that bus.
The corrupted frames match the ID and payload of frames received on CAN1.
This indicates a message RAM overlap between CAN0 and CAN1.
Environment
- Gateway board: Arduino Portenta C33 (RA6M5) with Portenta Breakout(ASX00031)
- Parent device: Arduino UNO R4 Minima (CAN0 side)
- Child device: Arduino UNO R4 WiFi (CAN1 side)
- Core version: Latest ArduinoCore-renesas (installed via Boards Manager)
- Library: Arduino_CAN (bundled with core)
- CAN transceivers: M5Stack U085 (SN65HVD230) × 4
- Bitrate: 500 kbps
- BOARDS MANAGER: Arduino Renesas Portenta Boards 1.5.1
Expected Behavior
- CAN0 and CAN1 should operate independently.
- Calling
CAN1.write()must not modify or corrupt CAN0’s receive FIFO. - CAN0 should only receive frames from its own physical CAN bus.
Actual Behavior
When CAN1.write(msg) is executed:
- CAN0 begins receiving frames with incorrect IDs.
- The corrupted ID always matches the reply ID from the device connected to CAN1.
- If the child device’s reply ID is changed (e.g., 0x022 → 0x025),
the corrupted ID on CAN0 also changes to the same value. - Payload bytes also match the frames received on CAN1.
This proves that CAN1 RX/TX data is leaking into CAN0 RX FIFO.
If CAN1.write() is commented out, the issue disappears completely.
Corrupted RX log on CAN0 (Portenta C33)
Below is an example of the corrupted frames received on CAN0 when CAN1.write() is enabled.
- The first frame (
[021]) is correct and comes from the parent device. - Immediately after that, CAN0 starts receiving frames with ID = 0x25,
even though 0x25 is the reply ID from the child device on CAN1,
and no such frame exists on the CAN0 bus. - All corrupted frames have the same payload as the child device’s reply.
15:26:37.963 -> Start
15:26:37.963 -> Received msg = [021] (8) : CAFE0000540E0000 <-- correct (from parent)
15:26:37.963 -> ACK_code = 1
15:26:37.963 -> Received msg = [025] (8) : CAFE0000540E0000 <-- incorrect (should never appear on CAN0)
15:26:37.963 -> ACK_code = 1
15:26:37.963 -> Received msg = [025] (8) : CAFE0000540E0000
15:26:37.963 -> ACK_code = 1
15:26:37.997 -> Received msg = [025] (8) : CAFE0000540E0000
15:26:37.997 -> ACK_code = 1
15:26:37.997 -> Received msg = [025] (8) : CAFE0000540E0000
15:26:37.997 -> ACK_code = 1
15:26:37.997 -> Received msg = [025] (8) : CAFE0000540E0000
15:26:37.997 -> ACK_code = 1
15:26:37.997 -> Received msg = [025] (8) : CAFE0000540E0000
15:26:37.997 -> ACK_code = 1
Code
1. Parent device (UNO R4 Minima)
#include <Arduino_CAN.h>
static uint32_t const CAN_ID = 0x21;
unsigned long previousMillis = 0;
const long interval = 1000;
void setup()
{
Serial.begin(115200);
if (!CAN.begin(CanBitRate::BR_500k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
static uint32_t msg_cnt = 0;
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
uint8_t const msg_data[] = {0xCA,0xFE,0,0,0,0,0,0};
memcpy((void *)(msg_data + 4), &msg_cnt, sizeof(msg_cnt));
CanMsg const msg(CanStandardId(CAN_ID), sizeof(msg_data), msg_data);
Serial.print("Sent msg = ");
Serial.println(msg);
int rc = CAN.write(msg);
Serial.print("ACK_code = ");
Serial.println(rc);
msg_cnt++;
}
}2. Gateway device (Arduino Portenta C33)
#include <Arduino_CAN.h>
void setup()
{
Serial.begin(115200);
//while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_500k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
#if (PIN_CAN1_STBY >= 0)
pinMode(PIN_CAN1_STBY, OUTPUT);
digitalWrite(PIN_CAN1_STBY, LOW);
#endif
if (!CAN1.begin(CanBitRate::BR_500k))
{
Serial.println("CAN1.begin(...) failed.");
for (;;) {}
}
delay(5000);
Serial.println("Start");
}
void loop()
{
// CAN0 --> CAN1
if (CAN.available())
{
CanMsg const msgR0 = CAN.read();
Serial.print("Received msg = ");
Serial.println(msgR0);
int const rc = CAN1.write(msgR0);
Serial.print("ACK_code = ");
Serial.println(rc);
}
/*
// CAN1 --> CAN0 (not used in this test)
if (CAN1.available())
{
CanMsg const msgR1 = CAN1.read();
Serial.println(msgR1);
int const rc1 = CAN.write(msgR1);
Serial.print("rc1 = ");
Serial.println(rc1);
}
*/
}3. Child device (Arduino UNO R4 WiFi)
#include <Arduino_CAN.h>
void setup()
{
Serial.begin(115200);
//while (!Serial) { }
if (!CAN.begin(CanBitRate::BR_500k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}
void loop()
{
if (CAN.available())
{
CanMsg const rx = CAN.read(); // Read message
CanMsg tx(CanStandardId(0x25), rx.data_length, rx.data);
delayMicroseconds(500);
int const rc = CAN.write(tx);
Serial.print("Sent msg = ");
Serial.println(tx);
Serial.print("ACK_code = ");
Serial.println(rc);
}
delay(1);
}Request
Please investigate the cause of the message RAM overlap between CAN0 and CAN1
on the Portenta C33 (RA6M5), and fix the memory allocation so that
CAN1.write() does not corrupt CAN0’s RX FIFO.