Issues with CANopenNode Library on NUCLEO-F767ZI

Hi everyone,

I’m working on a project using the NUCLEO-F767ZI board and I’m trying to integrate the CANopenNode library. I’ve created a custom_targets.json file for the NUCLEO-F767ZI and configured the necessary includes in my mbed_app.json file. However, I’m encountering several build errors that I can’t seem to resolve.

Here’s the content of my custom_targets.json:

{
    "NUCLEO_F767ZI": {
        "inherits": ["Target"],
        "core": "Cortex-M7F",
        "extra_labels": ["ST", "STM32", "STM32F7", "STM32F767"],
        "OUTPUT_EXT": "bin",
        "is_disk_virtual": true,
        "supported_toolchains": ["GCC_ARM", "ARM"],
        "device_name": "STM32F767ZITx",
        "detect_code": ["1234"]
    }
}

And here’s my mbed_app.json configuration:

{
    "target_overrides": {
        "*": {
            "target.features_add": ["CAN"],
            "target.macros_add": ["CANOPENNODE"],
            "target.extra_labels_add": ["CANopenNode"]
        }
    }
}

I have included the CANopenNode library and set up the includes for the CANopenNode headers. Despite this, I’m receiving numerous errors, primarily related to missing definitions and implicit declarations, such as:

unknown type name 'CO_SDO_t'
implicit declaration of function 'CO_OD_find' is invalid in C99 [-Wimplicit-function-declaration]
no member named 'ODExtensions' in 'struct (anonymous at /src/canopennode/301/CO_PDO.h:179:9)'
...

Here is a portion of the error log:

/src/canopennode/301/CO_PDO.c:236:15: warning: implicit declaration of function 'CO_OD_find' is invalid in C99 [-Wimplicit-function-declaration]
    entryNo = CO_OD_find(SDO, index);
              ^
/src/canopennode/301/CO_PDO.c:242:12: warning: implicit declaration of function 'CO_OD_getAttribute' is invalid in C99 [-Wimplicit-function-declaration]
    attr = CO_OD_getAttribute(SDO, entryNo, subIndex);
           ^
/src/canopennode/301/CO_PDO.c:244:26: error: use of undeclared identifier 'CO_ODA_RPDO_MAPABLE'
    if(R_T==0 && !((attr&CO_ODA_RPDO_MAPABLE) && (attr&CO_ODA_WRITEABLE))) return CO_SDO_AB_NO_MAP;   /* Object cannot be mapped to the PDO. */
                         ^
/src/canopennode/301/CO_PDO.c:246:26: error: use of undeclared identifier 'CO_ODA_TPDO_MAPABLE'
    if(R_T!=0 && !((attr&CO_ODA_TPDO_MAPABLE) && (attr&CO_ODA_READABLE))) return CO_SDO_AB_NO_MAP;   /* Object cannot be mapped to the PDO. */
                         ^
...
fatal error: too many errors emitted, stopping now [-ferror-limit=]
6 warnings and 20 errors generated.

I’ve double-checked the paths and ensured that all required header files are included. The errors persist, indicating issues with undefined types and functions. I’ve also verified that the CANopenNode library is correctly added to my project directory.

Any guidance on resolving these issues would be greatly appreciated. Is there something specific I might be missing in the configuration or setup for the NUCLEO-F767ZI?

Thank you in advance for your help!

Hello,

I do not have personal experiences with CANopenNode library but

  • The Nucleo-F767ZI is normally supported target so you not need any customization via custom_targets.json
  • The Nucleo-F767ZI supports CAN feature in default so it is not necessary to add this via mbed_app.json

For someone who will want to help you may be important to know which build system you use and a link to exact source of the library.

BR, Jan

Hello ,

#include "CANopen.h"
#include "mbed.h"

// Define CAN bus pins and baud rate
#define CAN_BUS_RX_PIN PA_11
#define CAN_BUS_TX_PIN PA_12
#define CAN_BUS_BAUD_RATE 500000

// Define the node ID and other configurations
#define NODE_ID 0x01
#define SDO_TIMEOUT 1000
#define FIRST_HB_TIME 1000
#define NMT_CONTROL 0x02

// Global variables
CAN can1(CAN_BUS_RX_PIN, CAN_BUS_TX_PIN, CAN_BUS_BAUD_RATE);
CO_t *CO = NULL;

void can1_irq_handler() {
    if (can1.readable()) {
        // Handle CAN receive interrupt
        CANMessage msg;
        if (can1.read(msg)) {
            CO_CANrxMsg_t rxMsg;
            rxMsg.ident = msg.id;
            rxMsg.DLC = msg.len;
            memcpy(rxMsg.data, msg.data, msg.len);
            CO_CANrxBufUpdate(CO->CANmodule, &rxMsg);
        }
    }
}

void can1_tx_handler() {
    // Handle CAN transmit interrupt
}

int main() {
    uint32_t heapMemoryUsed;
    CO_ReturnError_t err;
    CO_NMT_reset_cmd_t reset;
    uint32_t timerNext_us = 0;
    uint32_t timeDifference_us;
    Timer timer;

    // Initialize CANopen stack
    CO = CO_new(NULL, &heapMemoryUsed);
    if (CO == NULL) {
        printf("CANopen initialization failed\n");
        return -1;
    }

    // Initialize CAN hardware
    err = CO_CANinit(CO, &can1, CAN_BUS_BAUD_RATE);
    if (err != CO_ERROR_NO) {
        printf("CAN hardware initialization failed\n");
        return -1;
    }

    // Initialize LSS slave (if applicable)
#if ((CO_CONFIG_LSS) & CO_CONFIG_LSS_SLAVE)
    CO_LSSinit(CO, NULL, NULL, NULL);
#endif

    // Initialize CANopen objects
    err = CO_CANopenInit(CO, NULL, NULL, NULL, NULL, NMT_CONTROL, FIRST_HB_TIME, SDO_TIMEOUT, NODE_ID);
    if (err != CO_ERROR_NO) {
        printf("CANopen objects initialization failed\n");
        return -1;
    }

    // Attach CAN interrupt handlers
    can1.attach(&can1_irq_handler, CAN::RxIrq);
    can1.attach(&can1_tx_handler, CAN::TxIrq);

    // Start the timer
    timer.start();

    // Main loop
    while (1) {
        // Calculate time difference
        timeDifference_us = timer.read_us();
        timer.reset();

        // Process CANopen stack
        reset = CO_process(CO, false, timeDifference_us, &timerNext_us);
        
        // Process SYNC
#if ((CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE)
        CO_process_SYNC(CO, timeDifference_us, &timerNext_us);
#endif

        // Process RPDO
#if (CO_CONFIG_PDO) & CO_CONFIG_RPDO_ENABLE
        CO_process_RPDO(CO, false);
#endif

        // Process TPDO
#if (CO_CONFIG_PDO) & CO_CONFIG_TPDO_ENABLE
        CO_process_TPDO(CO, false, timeDifference_us, &timerNext_us);
#endif

        // Process SRDO
#if ((CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE)
        CO_process_SRDO(CO, timeDifference_us, &timerNext_us);
#endif

        // Handle reset commands
        if (reset == CO_RESET_COMM) {
            // Handle communication reset
        } else if (reset == CO_RESET_APP) {
            // Handle application reset
            break;
        }
    }

    // Cleanup
    CO_delete(CO);

    return 0;
}

this is the code I write .
I use this library GitHub - CANopenNode/CANopenNode: CANopen protocol stack

Thanks Jan.