Trying to get a can fd controller to work with h7 and breakout

Hello

I am trying to interface the portenta h7 and breakout board with spi devices.. but I am not able to connect to them as expected..
How do I define the cs and Int pins when using the arduino ide?
The device is the longan labs canfd shield… I need to connect four of these to the portenta ..
The setup works well on a uno if I try a send example.. but won’t compile on the mbed board.

I am getting a compilation error when I use this code:

/* 
  MCP2517/8 send a CAN frame
  
  CAN Bus baudrare for CAN2.0 as below,
  
  CAN20_5KBPS
  CAN20_10KBPS
  CAN20_20KBPS
  CAN20_25KBPS
  CAN20_31K25BPS
  CAN20_33KBPS
  CAN20_40KBPS
  CAN20_50KBPS
  CAN20_80KBPS
  CAN20_83K3BPS
  CAN20_95KBPS
  CAN20_100KBPS
  CAN20_125KBPS
  CAN20_200KBPS
  CAN20_250KBPS
  CAN20_500KBPS
  CAN20_666KBPS
  CAN20_800KBPS
  CAN20_1000KBPS
  
  CAN FD Shield - https://www.longan-labs.cc/1030012.html
  CANBed FD - https://www.longan-labs.cc/1030009.html
*/

#include <SPI.h>
#include "mcp2518fd_can.h"

// pins for CAN-FD Shield
//const int SPI_CS_PIN = 9;
//const int CAN_INT_PIN = 2;

// pins for CANBed FD
const int PIN_SPI_SS = 7;
// const int CAN_INT_PIN = 7;

mcp2518fd CAN(PIN_SPI_SS); // Set CS pin

void setup() {
    Serial.begin(115200);
    while(!Serial);

    while (CAN_OK != CAN.begin(CAN20_500KBPS)) {             // init can bus : baudrate = 500k
        Serial.println("CAN init fail, retry...");
        delay(100);
    }
    Serial.println("CAN init ok!");
}

unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};

void loop() {

    CAN.sendMsgBuf(0x01, 0, 8, stmp);       // send a standard frame to id 0x01
    delay(10);
    CAN.sendMsgBuf(0x04, 1, 8, stmp);       // send a extended frame to id 0x04
    delay(100);                       // send data per 100ms
    Serial.println("CAN BUS sendMsgBuf ok!");
}

// END FILE

Error:

In file included from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/stm32h7xx_hal_conf.h:402:0,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal.h:30,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/CMSIS/stm32h7xx.h:223,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/cmsis.h:22,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/PinNamesTypes.h:33,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/variants/PORTENTA_H7_M7/pinmode_arduino.h:24,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/Arduino.h:26,
                 from /private/var/folders/1k/nvt5g3fn39lg04gqml_9csmh0000gn/T/arduino/sketches/CFE45A8F9137959CB84700EA2A10C3AF/sketch/CAN20_SEND.ino.cpp:1:
/Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_gpio.h:86:36: error: expected identifier before '(' token
 #define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
                                    ^
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:663:16: note: in expansion of macro 'GPIO_PIN_0'
 typedef enum { GPIO_PIN_0, GPIO_PIN_1 } GPIO_PIN_POS;
                ^
/Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_gpio.h:86:36: error: expected '}' before '(' token
 #define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
                                    ^
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:663:16: note: in expansion of macro 'GPIO_PIN_0'
 typedef enum { GPIO_PIN_0, GPIO_PIN_1 } GPIO_PIN_POS;
                ^
/Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_gpio.h:86:47: error: expected ')' before numeric constant
 #define GPIO_PIN_0                 ((uint16_t)0x0001)  /* Pin 0 selected    */
                                               ^
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:663:16: note: in expansion of macro 'GPIO_PIN_0'
 typedef enum { GPIO_PIN_0, GPIO_PIN_1 } GPIO_PIN_POS;
                ^
In file included from /Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can.h:6:0,
                 from /private/var/folders/1k/nvt5g3fn39lg04gqml_9csmh0000gn/T/.arduinoIDE-unsaved202515-48523-6l12ni.2xsp/CAN20_SEND/CAN20_SEND.ino:31:
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:663:41: error: 'GPIO_PIN_POS' does not name a type; did you mean 'GPIO_PIN_SET'?
 typedef enum { GPIO_PIN_0, GPIO_PIN_1 } GPIO_PIN_POS;
                                         ^~~~~~~~~~~~
                                         GPIO_PIN_SET
In file included from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/CMSIS/stm32h7xx.h:136:0,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/cmsis.h:22,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/PinNamesTypes.h:33,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/variants/PORTENTA_H7_M7/pinmode_arduino.h:24,
                 from /Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/Arduino.h:26,
                 from /private/var/folders/1k/nvt5g3fn39lg04gqml_9csmh0000gn/T/arduino/sketches/CFE45A8F9137959CB84700EA2A10C3AF/sketch/CAN20_SEND.ino.cpp:1:
/Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/CMSIS/stm32h747xx.h:2698:43: error: expected ')' before '*' token
 #define CRC                 ((CRC_TypeDef *) CRC_BASE)
                                           ^
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:1487:14: note: in expansion of macro 'CRC'
     uint32_t CRC : 16;
              ^
/Users/user/Library/Arduino15/packages/arduino/hardware/mbed_portenta/4.2.1/cores/arduino/mbed/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/CMSIS/stm32h747xx.h:2698:43: error: expected ')' before '*' token
 #define CRC                 ((CRC_TypeDef *) CRC_BASE)
                                           ^
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:1487:14: note: in expansion of macro 'CRC'
     uint32_t CRC : 16;
              ^
In file included from /Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can.h:6:0,
                 from /private/var/folders/1k/nvt5g3fn39lg04gqml_9csmh0000gn/T/.arduinoIDE-unsaved202515-48523-6l12ni.2xsp/CAN20_SEND/CAN20_SEND.ino:31:
/Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h:1590:1: error: expected declaration before '}' token
 }
 ^

exit status 1

Compilation error: exit status 1

Hi @thechordmaster. The problem is that there is a collision between macros defined in the "Arduino Mbed OS Portenta Boards" core and identifiers used by the "Longan_CANFD" library.

The solution will be to change the colliding identifiers in the Longan_CANFD library to have unique names. I'll provide instructions you can follow to do that:

  1. Use any text editor to open the file at the following path on your hard drive:
    /Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can.cpp
    
  2. Change line 2231 from this:
    if (pin == GPIO_PIN_0) {
    
    to this:
    if (pin == LONGAN_CANFD_GPIO_PIN_0) {
    
  3. Change line 2235 from this:
    if (pin == GPIO_PIN_1) {
    
    to this:
    if (pin == LONGAN_CANFD_GPIO_PIN_1) {
    
  4. Change line 2264 from this:
    case GPIO_PIN_0:
    
    to this:
    case LONGAN_CANFD_GPIO_PIN_0:
    
  5. Change line 2267 from this:
    case GPIO_PIN_1:
    
    to this:
    case LONGAN_CANFD_GPIO_PIN_1:
    
  6. Change line 2299 from this:
    case GPIO_PIN_0:
    
    to this:
    case LONGAN_CANFD_GPIO_PIN_0:
    
  7. Change line 2302 from this:
    case GPIO_PIN_1:
    
    to this:
    case LONGAN_CANFD_GPIO_PIN_1:
    
  8. Save the file.
  9. Use any text editor to open the file at the following path on your hard drive:
    /Users/user/Documents/Arduino/libraries/Longan_CANFD/src/mcp2518fd_can_dfs.h
    
  10. Change line 663 from this:
    typedef enum { GPIO_PIN_0, GPIO_PIN_1 } GPIO_PIN_POS;
    
    to this:
    typedef enum { LONGAN_CANFD_GPIO_PIN_0, LONGAN_CANFD_GPIO_PIN_1 } GPIO_PIN_POS;
    
  11. Change line 1487 from this:
    uint32_t CRC : 16;
    
    to this:
    uint32_t LONGAN_CANFD_CRC : 16;
    
  12. Save the file

The instructions above are equivalent to applying this patch:

diff --git a/src/mcp2518fd_can.cpp b/src/mcp2518fd_can.cpp
index df5483f..c8600aa 100644
--- a/src/mcp2518fd_can.cpp
+++ b/src/mcp2518fd_can.cpp
@@ -2228,11 +2228,11 @@ bool mcp2518fd::mcpPinMode(const byte pin, const byte mode) {

     mcp2518fd_ReadByte(a, &iocon.byte[3]);

-    if (pin == GPIO_PIN_0) {
+    if (pin == LONGAN_CANFD_GPIO_PIN_0) {
         // Modify
         iocon.bF.PinMode0 = (GPIO_PIN_MODE)mode;
     }
-    if (pin == GPIO_PIN_1) {
+    if (pin == LONGAN_CANFD_GPIO_PIN_1) {
         // Modify
         iocon.bF.PinMode1 = (GPIO_PIN_MODE)mode;
     }
@@ -2261,10 +2261,10 @@ bool mcp2518fd::mcpDigitalWrite(const byte pin, const byte mode) {

     // Modify
     switch (pin) {
-        case GPIO_PIN_0:
+        case LONGAN_CANFD_GPIO_PIN_0:
         iocon.bF.LAT0 = (GPIO_PIN_STATE)mode;
         break;
-        case GPIO_PIN_1:
+        case LONGAN_CANFD_GPIO_PIN_1:
         iocon.bF.LAT1 = (GPIO_PIN_STATE)mode;
         break;
         default:
@@ -2296,10 +2296,10 @@ byte mcp2518fd::mcpDigitalRead(const byte pin) {

     // Update data
     switch (pin) {
-        case GPIO_PIN_0:
+        case LONGAN_CANFD_GPIO_PIN_0:
         state = (GPIO_PIN_STATE)iocon.bF.GPIO0;
         break;
-        case GPIO_PIN_1:
+        case LONGAN_CANFD_GPIO_PIN_1:
         state = (GPIO_PIN_STATE)iocon.bF.GPIO1;
         break;
         default:
diff --git a/src/mcp2518fd_can_dfs.h b/src/mcp2518fd_can_dfs.h
index 2562dc4..d360409 100644
--- a/src/mcp2518fd_can_dfs.h
+++ b/src/mcp2518fd_can_dfs.h
@@ -660,7 +660,7 @@ typedef enum {

 //! GPIO Pin Position

-typedef enum { GPIO_PIN_0, GPIO_PIN_1 } GPIO_PIN_POS;
+typedef enum { LONGAN_CANFD_GPIO_PIN_0, LONGAN_CANFD_GPIO_PIN_1 } GPIO_PIN_POS;

 //! GPIO Pin Modes

@@ -1484,7 +1484,7 @@ typedef union _REG_IOCON {
 typedef union _REG_CRC {

   struct {
-    uint32_t CRC : 16;
+    uint32_t LONGAN_CANFD_CRC : 16;
     uint32_t CRCERRIF : 1;
     uint32_t FERRIF : 1;
     uint32_t unimplemented1 : 6;

There is also a bug in your sketch. Remove this line:

PIN_SPI_SS is already defined by the "Arduino Mbed OS Portenta Boards" core:

1 Like

In order to make all relevant information available to any who are interested in this subject, I'll share a link to the formal report @thechordmaster submitted to the Longan_CANFD library developers:

1 Like

Oh goodness me thank you.. let me try it out..
Also as I understand these steps are to mitigate the compilation error right? Now if I was to just remove the lines instead of renaming, I may run into an issue with another line in the code that depends on the removed line.. am I right?

Now is there a general step by step process to mitigate similar errors with other spi devices that work on other platforms of Arduinos ?
Or is there a “if you see this error try doing this” sort of a document that users may face when using atmel board codes on mbed ones?

I doubt it...
A good rule of thumb is to not try to run atmel code on mbed boards. Pin description is only the first error you will encounter.

In my opinion, you have chosen a very difficult task, you do not have the experience to complete it yet. Are you sure that you need to do it on potenta?

This board was chosen by the customer due to the faster processor which is essential for their requirements..

As for me, a choosing the board is a developer's business, not a customer

1 Like

Correct.

It seems the situation is not clear to you, so I'll provide a more detailed explanation. There are actually three distinct name collisions, but the nature of all three is the same so I'll explain only the first of them:

A macro named GPIO_PIN_0 is defined by the "Arduino Mbed OS Portenta Boards" core that implements the standard Arduino API for the Portenta H7 board:

The Longan_CANFD library developers also happened to use the name GPIO_PIN_0 as an enumerator in the library's GPIO_PIN_POS type:

The core's definition of the GPIO_PIN_0 macro is visible to the code in mcp2518fd_can_dfs.h via the #include directive for Arduino.h in that file:

So there is a name collision. Because one of the two is a macro, the resulting compilation error is quite cryptic.

We can distill the cause of the compilation error down to this minimal program:

#define SOME_COLLIDING_NAME ()
enum foo_t { SOME_COLLIDING_NAME };
void setup() {}
void loop() {}

Yes. At least with the GPIO_PIN_POS type, the code is in the library for a reason. If you remove the code then you break the library. It is possible you could remove REG_CRC as I didn't actually find that it was used anywhere, but it is just as easy to modify it as to remove it so I don't see the point in doing that.

This doesn't have anything to do with SPI. It is simply a matter of the developers of the two separate code bases happening to have chosen the same names.

It is a problem you will encounter periodically in any software development work. It is especially likely to occur when developers use common generic terms like CRC as names, especially when those names are exposed in the global namespace.

There is no "step by step process", but you can learn various techniques for resolving name collisions. You see one technique here, which is to change one to a unique name.

Although it is true that you will encounter errors when trying to use a library that has architecture-specific code with a board of a different architecture, that was not the case here.

This doesn't have anything to do with "atmel"has nothing to do with

An alternative approach to resolving the collision is described here:

https://github.com/arduino/ArduinoCore-mbed/issues/998#issuecomment-2642598893

the solution would be to #undef GPIO_PIN_0 and #undef GPIO_PIN_1 after including "Arduino.h"

diff --git a/src/mcp2518fd_can_dfs.h b/src/mcp2518fd_can_dfs.h
index 154353f..05bbb8e 100644
--- a/src/mcp2518fd_can_dfs.h
+++ b/src/mcp2518fd_can_dfs.h
@@ -49,6 +49,10 @@ DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
#include <inttypes.h>
#include "mcp_can_fd.h"

+#undef GPIO_PIN_0
+#undef GPIO_PIN_1
+#undef CRC
+

Unfortunately the ST headers are quite invasive and "pollute" Arduino.h

The code does compile, but i don't see any data on serial comms.
i will try to scope out the data lines , in the meantime if anyone can try out on their end will helpful.

we have this setup.. like you said.. there is no data or serial comms...how can we debug?

would this help?

is the issue the way the spi pins are addressed?