Hello,
after successfully running the M7 core and being able to communicate via UART4, I am now struggling with FLEXCAN1.
I’m using a verdin imx8mp v1.1B 4GB IT SOM (Without BT/WiFi module) on a Dahlia v1.1D Carrier Board and started a project based on “flexcan_interrupt_transfer” example. MCUXpresso SDK version is 2026.03.00.
Whenever I am trying to send something via FLEXCAN_TransferSendNonBlocking, the transfer callback function gets invoked once with status kStatus_FLEXCAN_UnHandled and afterwards gets continuesly invoked with status kStatus_FLEXCAN_ErrorStatus.
Whenever I am trying to receive something via FLEXCAN_TransferReceiveNonBlocking, the transfer callback function gets invoked once with status kStatus_FLEXCAN_UnHandled as well.
R1 is not assembled on the Dahlia Board and the S / Pin 8 of MCP2558 is tied to GND.
I have configured AD18/SPDIF_RX as CAN1 RX with Pull Up enabled and AE18/SPDIF_TX as CAN1 TX With Pull Up enabled (tried with pull up resistor disabled on both as well). This is the resulting Board_InitPins ind pin_mux.c:
void BOARD_InitPins(void) {
IOMUXC_SetPinMux(IOMUXC_SPDIF_RX_CAN1_RX, 0U);
IOMUXC_SetPinConfig(IOMUXC_SPDIF_RX_CAN1_RX,
IOMUXC_SW_PAD_CTL_PAD_DSE(3U) |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
IOMUXC_SetPinMux(IOMUXC_SPDIF_TX_CAN1_TX, 0U);
IOMUXC_SetPinConfig(IOMUXC_SPDIF_TX_CAN1_TX,
IOMUXC_SW_PAD_CTL_PAD_DSE(3U) |
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
IOMUXC_SetPinMux(IOMUXC_UART4_RXD_UART4_RX, 0U);
IOMUXC_SetPinConfig(IOMUXC_UART4_RXD_UART4_RX,
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
IOMUXC_SetPinMux(IOMUXC_UART4_TXD_UART4_TX, 0U);
IOMUXC_SetPinConfig(IOMUXC_UART4_TXD_UART4_TX,
IOMUXC_SW_PAD_CTL_PAD_PUE_MASK |
IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
}
I am using imx8mp-verdin-nonwifi-dev.dtb devicetree and I have disabled flexcan1 in the applied dtbo file. This is the full device tree overlay:
/dts-v1/;
/plugin/;
/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/clock/imx8mp-clock.h>
/ {
model = "Toradex Verdin iMX8M Plus";
compatible = "toradex,verdin-imx8mp";
};
&{/} {
imx8mp-cm7 {
compatible = "fsl,imx8mp-cm7";
clocks = <&clk IMX8MP_CLK_M7_DIV>;
mbox-names = "tx", "rx", "rxdb";
mboxes = <&mu 0 1
&mu 1 1
&mu 3 1>;
memory-region = <&vdevbuffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>, <&m7_reserved>;
rsc-da = <0x55000000>;
syscon = <&src>;
fsl,startup-delay-ms = <500>;
};
};
&resmem {
#address-cells = <2>;
#size-cells = <2>;
m7_reserved: m7@80000000 {
no-map;
reg = <0 0x80000000 0 0x1000000>;
};
vdev0vring0: vdev0vring0@55000000 {
no-map;
reg = <0 0x55000000 0 0x8000>;
};
vdev0vring1: vdev0vring1@55008000 {
no-map;
reg = <0 0x55008000 0 0x8000>;
};
vdevbuffer: vdevbuffer@55400000 {
compatible = "shared-dma-pool";
no-map;
reg = <0 0x55400000 0 0x100000>;
};
rsc_table: rsc-table@550ff000 {
no-map;
reg = <0 0x550ff000 0 0x1000>;
};
};
&flexcan1 {
status = "disabled";
};
&flexcan2 {
status = "disabled";
};
&i2c3 {
status = "disabled";
};
&pwm4 {
status = "disabled";
};
&sai3 {
status = "disabled";
};
&sdma3 {
status = "disabled";
};
&uart4 {
status = "disabled";
};
&aud2htx {
status = "okay";
};
&gpu_2d {
status = "okay";
};
&gpu_3d {
status = "okay";
};
&hdmi {
status = "okay";
};
&hdmiphy {
status = "okay";
};
&hdmi_blk_ctrl {
status = "okay";
};
&hdmi_pavi {
status = "okay";
};
&irqsteer_hdmi {
status = "okay";
};
&lcdif3 {
status = "okay";
};
&ml_vipsi {
status = "okay";
};
&mix_gpu_ml {
status = "okay";
};
&sound_hdmi {
status = "okay";
};
&vpu_g1 {
status = "okay";
};
&vpu_g2 {
status = "okay";
};
&vpu_vc8000e {
status = "okay";
};
&vpu_v4l2 {
status = "okay";
};
This is my main.c file:
/*
* Copyright (c) 2013 - 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017, 2024 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "board.h"
#include "app.h"
#include "version.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define DLC (8)
#define EXAMPLE_CAN_CLK_FREQ \
(CLOCK_GetPllFreq(kCLOCK_SystemPll1Ctrl) / (CLOCK_GetRootPreDivider(kCLOCK_RootFlexCan1)) / \
(CLOCK_GetRootPostDivider(kCLOCK_RootFlexCan1)))
#define RX_MESSAGE_BUFFER_NUM (9)
#define TX_MESSAGE_BUFFER_NUM (8)
#define EXAMPLE_CAN FLEXCAN1
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
volatile bool rxComplete = false;
volatile bool wakenUp = false;
flexcan_mb_transfer_t txXfer, rxXfer;
flexcan_frame_t frame;
uint32_t txIdentifier;
uint32_t rxIdentifier;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief CAN transceiver configuration function
*/
static void FLEXCAN_PHY_Config(void)
{
}
/*!
* @brief FlexCAN Call Back function
*/
static FLEXCAN_CALLBACK(flexcan_callback)
{
switch (status)
{
case kStatus_FLEXCAN_TxBusy:
PRINTF("TxBusy");
break;
case kStatus_FLEXCAN_RxBusy:
PRINTF("RxBusy");
break;
case kStatus_FLEXCAN_TxSwitchToRx:
PRINTF("TxToRx");
break;
case kStatus_FLEXCAN_RxOverflow:
PRINTF("RxOverflow");
break;
case kStatus_FLEXCAN_RxFifoBusy:
PRINTF("RxFifoBusy");
break;
case kStatus_FLEXCAN_RxFifoIdle:
PRINTF("Rxfifoidl");
break;
case kStatus_FLEXCAN_RxFifoOverflow:
PRINTF("RxfifoOver");
break;
case kStatus_FLEXCAN_RxFifoWarning:
PRINTF("RxFifoWarn");
break;
case kStatus_FLEXCAN_RxFifoDisabled:
PRINTF("RxFifoDis");
break;
case kStatus_FLEXCAN_ErrorStatus:
PRINTF("Error %d", result);
break;
case kStatus_FLEXCAN_RxRemote:
PRINTF("RxRemote");
break;
case kStatus_FLEXCAN_MemoryError:
PRINTF("Memory");
break;
case kStatus_FLEXCAN_RxIdle:
if (RX_MESSAGE_BUFFER_NUM == result)
{
rxComplete = true;
}
break;
case kStatus_FLEXCAN_TxIdle:
if (TX_MESSAGE_BUFFER_NUM == result)
{
txComplete = true;
}
break;
case kStatus_FLEXCAN_WakeUp:
wakenUp = true;
break;
case kStatus_FLEXCAN_UnHandled:
default:
PRINTF("Unhandled");
break;
}
}
/*!
* @brief Main function
*/
int main(void)
{
char ch;
/* Init board hardware. */
BOARD_InitHardware();
PRINTF("%s running\r\n", DEV_STR_NAME);
PRINTF("FW version: %d.%d.%d\r\n", SW_VER_MAJOR, SW_VER_MINOR, SW_VER_REV);
PRINTF("SDK version: %s\r\n", MCUXSDK_VERSION_FULL_STR);
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
uint8_t node_type;
do
{
PRINTF("Please select local node as A or B:\r\n");
PRINTF("Note: Node B should start first.\r\n");
PRINTF("Node:");
node_type = GETCHAR();
PRINTF("%c", node_type);
PRINTF("\r\n");
} while ((node_type != 'A') && (node_type != 'B') && (node_type != 'a') && (node_type != 'b'));
/* Select mailbox ID. */
if ((node_type == 'A') || (node_type == 'a'))
{
txIdentifier = 0x321;
rxIdentifier = 0x123;
}
else
{
txIdentifier = 0x123;
rxIdentifier = 0x321;
}
/* Get FlexCAN module default Configuration. */
/*
* flexcanConfig.clkSrc = kFLEXCAN_ClkSrc0;
* flexcanConfig.bitRate = 1000000U;
* flexcanConfig.bitRateFD = 2000000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.disableSelfReception = false;
* flexcanConfig.enableListenOnlyMode = false;
* flexcanConfig.enableDoze = false;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);
flexcanConfig.bitRate = 125000U;
flexcan_timing_config_t timing_config;
memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
if (FLEXCAN_CalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);
/* Create FlexCAN handle structure and set call back function. */
FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &flexcanHandle, flexcan_callback, NULL);
/* Set Rx Masking mechanism. */
FLEXCAN_SetRxMbGlobalMask(EXAMPLE_CAN, FLEXCAN_RX_MB_STD_MASK(rxIdentifier, 0, 0));
/* Setup Rx Message Buffer. */
mbConfig.format = kFLEXCAN_FrameFormatStandard;
mbConfig.type = kFLEXCAN_FrameTypeData;
mbConfig.id = FLEXCAN_ID_STD(rxIdentifier);
FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
/* Setup Tx Message Buffer. */
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
/* Configure CAN transceiver */
FLEXCAN_PHY_Config();
if ((node_type == 'A') || (node_type == 'a'))
{
PRINTF("Press any key to trigger one-shot transmission\r\n\r\n");
frame.dataByte0 = 0;
}
else
{
PRINTF("Start to Wait data from Node A\r\n\r\n");
}
while (true)
{
if ((node_type == 'A') || (node_type == 'a'))
{
GETCHAR();
PRINTF("Start transfer!\r\n\r\n");
frame.id = FLEXCAN_ID_STD(txIdentifier);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = (uint8_t)DLC;
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
while (!txComplete)
{
};
txComplete = false;
PRINTF("Press any key to trigger the next transmission!\r\n\r\n");
frame.dataByte0++;
frame.dataByte1 = 0x55;
}
else
{
/* Before this , should first make node B enter STOP mode after FlexCAN
* initialized with enableSelfWakeup=true and Rx MB configured, then A
* sends frame N which wakes up node B. A will continue to send frame N
* since no acknowledgement, then B received the second frame N(In the
* application it seems that B received the frame that woke it up which
* is not expected as stated in the reference manual, but actually the
* output in the terminal B received is the same second frame N). */
if (wakenUp)
{
PRINTF("B has been waken up!\r\n\r\n");
}
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
/* Wait until Rx receive full. */
while (!rxComplete)
{
};
rxComplete = false;
PRINTF("Rx MB ID: 0x%3x, Rx MB data: 0x%x, Time stamp: %d\r\n", frame.id >> CAN_ID_STD_SHIFT,
frame.dataByte0, frame.timestamp);
frame.id = FLEXCAN_ID_STD(txIdentifier);
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
while (!txComplete)
{
};
txComplete = false;
PRINTF("Wait Node A to trigger the next transmission!\r\n\r\n");
}
}
while (1)
{
ch = GETCHAR();
PUTCHAR(ch);
}
}