Thank You all for your support. The above example given by @Lukas_Frank is "flexcan_interrupt_transfer" as an SDK example. I wanted transmission and reception simultaneously so I removed the node A and node B part. If you have multiple CAN frames like I did, make a function.
Hi
There is CAN support integrated into the i.MX RT 1064 project solution at this reference: https://www.utasker.com/iMX/RT1064.html#CAN1
It also includes CANopen for the i.MX RT 1064 integrated into a turn-key solution with USB device/host, CAN, TCP/IP, file system, graphics and various other specific modules.
Regards
Mark
For i.MX and Kinetis stock availability see https://www.utasker.com/Shop/semi.html
Hi @GSR1 ,
Did you tried example below? I will be following the issue.
Best
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_CAN CAN3
/* Considering that the first valid MB must be used as Reserved TX MB for ERR005829,
* if RX FIFO enables (RFEN bit in MCE set as 1) and RFFN in CTRL2 is set default as zero,
* the first valid TX MB Number shall be 8;
* if RX FIFO enables (RFEN bit in MCE set as 1) and RFFN in CTRL2 is set by other values (0x1~0xF),
* the user should consider to detail the first valid MB number;
* if RX FIFO disables (RFEN bit in MCE set as 0) , the first valid MB number would be zero.
*/
#define RX_MESSAGE_BUFFER_NUM (10)
#define TX_MESSAGE_BUFFER_NUM (9)
#define USE_CANFD (1)
#define EXAMPLE_CAN_CLK_SOURCE (kFLEXCAN_ClkSrc1)
/* Select 60M clock divided by USB1 PLL (480 MHz) as master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (2U)
/* Get frequency of flexcan clock */
#define EXAMPLE_CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
/* Set USE_IMPROVED_TIMING_CONFIG macro to use api to calculates the improved CAN / CAN FD timing values. */
#define USE_IMPROVED_TIMING_CONFIG (1U)
/* Fix MISRA_C-2012 Rule 17.7. */
#define LOG_INFO (void)PRINTF
#if (defined(USE_CANFD) && USE_CANFD)
/*
* DWORD_IN_MB DLC BYTES_IN_MB Maximum MBs
* 2 8 kFLEXCAN_8BperMB 64
* 4 10 kFLEXCAN_16BperMB 42
* 8 13 kFLEXCAN_32BperMB 25
* 16 15 kFLEXCAN_64BperMB 14
*
* Dword in each message buffer, Length of data in bytes, Payload size must align,
* and the Message Buffers are limited corresponding to each payload configuration:
*/
#define DLC (15)
#define BYTES_IN_MB kFLEXCAN_64BperMB
#else
#define DLC (8)
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
volatile bool rxComplete = false;
volatile bool wakenUp = false;
flexcan_mb_transfer_t txXfer, rxXfer;
#if (defined(USE_CANFD) && USE_CANFD)
flexcan_fd_frame_t frame;
#else
flexcan_frame_t frame;
#endif
uint32_t txIdentifier;
uint32_t rxIdentifier;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief FlexCAN Call Back function
*/
static FLEXCAN_CALLBACK(flexcan_callback)
{
switch (status)
{
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;
default:
break;
}
}
/*!
* @brief Main function
*/
int main(void)
{
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
uint8_t node_type;
/* Initialize board hardware. */
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/*Clock setting for FLEXCAN*/
CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);
LOG_INFO("********* FLEXCAN Interrupt EXAMPLE *********\r\n");
LOG_INFO(" Message format: Standard (11 bit id)\r\n");
LOG_INFO(" Message buffer %d used for Rx.\r\n", RX_MESSAGE_BUFFER_NUM);
LOG_INFO(" Message buffer %d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
LOG_INFO(" Interrupt Mode: Enabled\r\n");
LOG_INFO(" Operation Mode: TX and RX --> Normal\r\n");
LOG_INFO("*********************************************\r\n\r\n");
do
{
LOG_INFO("Please select local node as A or B:\r\n");
LOG_INFO("Note: Node B should start first.\r\n");
LOG_INFO("Node:");
node_type = GETCHAR();
LOG_INFO("%c", node_type);
LOG_INFO("\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);
#if defined(EXAMPLE_CAN_CLK_SOURCE)
flexcanConfig.clksrc=EXAMPLE_CAN_CLK_SOURCE;
#endif
#if defined(EXAMPLE_CAN_BIT_RATE)
flexcanConfig.bitRate = EXAMPLE_CAN_BIT_RATE;
#endif
/* If special quantum setting is needed, set the timing parameters. */
#if (defined(SET_CAN_QUANTUM) && SET_CAN_QUANTUM)
flexcanConfig.timingConfig.phaseSeg1 = PSEG1;
flexcanConfig.timingConfig.phaseSeg2 = PSEG2;
flexcanConfig.timingConfig.propSeg = PROPSEG;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
flexcanConfig.timingConfig.fphaseSeg1 = FPSEG1;
flexcanConfig.timingConfig.fphaseSeg2 = FPSEG2;
flexcanConfig.timingConfig.fpropSeg = FPROPSEG;
#endif
#endif
#if (defined(USE_IMPROVED_TIMING_CONFIG) && USE_IMPROVED_TIMING_CONFIG)
flexcan_timing_config_t timing_config;
memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
#if (defined(USE_CANFD) && USE_CANFD)
if (FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, flexcanConfig.bitRateFD,
EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#else
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));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#endif
#endif
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_FDInit(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ, BYTES_IN_MB, true);
#else
FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);
#endif
/* 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);
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_SetFDRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
#else
FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
#endif
/* Setup Tx Message Buffer. */
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_SetFDTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#else
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#endif
if ((node_type == 'A') || (node_type == 'a'))
{
LOG_INFO("Press any key to trigger one-shot transmission\r\n\r\n");
frame.dataByte0 = 0;
}
else
{
LOG_INFO("Start to Wait data from Node A\r\n\r\n");
}
while (true)
{
if ((node_type == 'A') || (node_type == 'a'))
{
GETCHAR();
frame.id = FLEXCAN_ID_STD(txIdentifier);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = (uint8_t)DLC;
#if (defined(USE_CANFD) && USE_CANFD)
frame.brs = 1U;
frame.edl = 1U;
#endif
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
(void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif
/* Wait until Rx MB full. */
while (!rxComplete)
{
};
rxComplete = false;
LOG_INFO("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);
LOG_INFO("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)
{
LOG_INFO("B has been waken up!\r\n\r\n");
}
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
(void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif
/* Wait until Rx receive full. */
while (!rxComplete)
{
};
rxComplete = false;
LOG_INFO("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;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
LOG_INFO("Wait Node A to trigger the next transmission!\r\n\r\n");
}
}
}
/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_CAN CAN3
/* Considering that the first valid MB must be used as Reserved TX MB for ERR005829,
* if RX FIFO enables (RFEN bit in MCE set as 1) and RFFN in CTRL2 is set default as zero,
* the first valid TX MB Number shall be 8;
* if RX FIFO enables (RFEN bit in MCE set as 1) and RFFN in CTRL2 is set by other values (0x1~0xF),
* the user should consider to detail the first valid MB number;
* if RX FIFO disables (RFEN bit in MCE set as 0) , the first valid MB number would be zero.
*/
#define RX_MESSAGE_BUFFER_NUM (10)
#define TX_MESSAGE_BUFFER_NUM (9)
#define USE_CANFD (1)
#define EXAMPLE_CAN_CLK_SOURCE (kFLEXCAN_ClkSrc1)
/* Select 60M clock divided by USB1 PLL (480 MHz) as master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_SELECT (0U)
/* Clock divider for master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (2U)
/* Get frequency of flexcan clock */
#define EXAMPLE_CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
/* Set USE_IMPROVED_TIMING_CONFIG macro to use api to calculates the improved CAN / CAN FD timing values. */
#define USE_IMPROVED_TIMING_CONFIG (1U)
/* Fix MISRA_C-2012 Rule 17.7. */
#define LOG_INFO (void)PRINTF
#if (defined(USE_CANFD) && USE_CANFD)
/*
* DWORD_IN_MB DLC BYTES_IN_MB Maximum MBs
* 2 8 kFLEXCAN_8BperMB 64
* 4 10 kFLEXCAN_16BperMB 42
* 8 13 kFLEXCAN_32BperMB 25
* 16 15 kFLEXCAN_64BperMB 14
*
* Dword in each message buffer, Length of data in bytes, Payload size must align,
* and the Message Buffers are limited corresponding to each payload configuration:
*/
#define DLC (15)
#define BYTES_IN_MB kFLEXCAN_64BperMB
#else
#define DLC (8)
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
volatile bool rxComplete = false;
volatile bool wakenUp = false;
flexcan_mb_transfer_t txXfer, rxXfer;
#if (defined(USE_CANFD) && USE_CANFD)
flexcan_fd_frame_t frame;
#else
flexcan_frame_t frame;
#endif
uint32_t txIdentifier;
uint32_t rxIdentifier;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief FlexCAN Call Back function
*/
static FLEXCAN_CALLBACK(flexcan_callback)
{
switch (status)
{
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;
default:
break;
}
}
/*!
* @brief Main function
*/
int main(void)
{
flexcan_config_t flexcanConfig;
flexcan_rx_mb_config_t mbConfig;
uint8_t node_type;
/* Initialize board hardware. */
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/*Clock setting for FLEXCAN*/
CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);
LOG_INFO("********* FLEXCAN Interrupt EXAMPLE *********\r\n");
LOG_INFO(" Message format: Standard (11 bit id)\r\n");
LOG_INFO(" Message buffer %d used for Rx.\r\n", RX_MESSAGE_BUFFER_NUM);
LOG_INFO(" Message buffer %d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
LOG_INFO(" Interrupt Mode: Enabled\r\n");
LOG_INFO(" Operation Mode: TX and RX --> Normal\r\n");
LOG_INFO("*********************************************\r\n\r\n");
do
{
LOG_INFO("Please select local node as A or B:\r\n");
LOG_INFO("Note: Node B should start first.\r\n");
LOG_INFO("Node:");
node_type = GETCHAR();
LOG_INFO("%c", node_type);
LOG_INFO("\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);
#if defined(EXAMPLE_CAN_CLK_SOURCE)
flexcanConfig.clksrc=EXAMPLE_CAN_CLK_SOURCE;
#endif
#if defined(EXAMPLE_CAN_BIT_RATE)
flexcanConfig.bitRate = EXAMPLE_CAN_BIT_RATE;
#endif
/* If special quantum setting is needed, set the timing parameters. */
#if (defined(SET_CAN_QUANTUM) && SET_CAN_QUANTUM)
flexcanConfig.timingConfig.phaseSeg1 = PSEG1;
flexcanConfig.timingConfig.phaseSeg2 = PSEG2;
flexcanConfig.timingConfig.propSeg = PROPSEG;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
flexcanConfig.timingConfig.fphaseSeg1 = FPSEG1;
flexcanConfig.timingConfig.fphaseSeg2 = FPSEG2;
flexcanConfig.timingConfig.fpropSeg = FPROPSEG;
#endif
#endif
#if (defined(USE_IMPROVED_TIMING_CONFIG) && USE_IMPROVED_TIMING_CONFIG)
flexcan_timing_config_t timing_config;
memset(&timing_config, 0, sizeof(flexcan_timing_config_t));
#if (defined(USE_CANFD) && USE_CANFD)
if (FLEXCAN_FDCalculateImprovedTimingValues(EXAMPLE_CAN, flexcanConfig.bitRate, flexcanConfig.bitRateFD,
EXAMPLE_CAN_CLK_FREQ, &timing_config))
{
/* Update the improved timing configuration*/
memcpy(&(flexcanConfig.timingConfig), &timing_config, sizeof(flexcan_timing_config_t));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#else
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));
}
else
{
LOG_INFO("No found Improved Timing Configuration. Just used default configuration\r\n\r\n");
}
#endif
#endif
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_FDInit(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ, BYTES_IN_MB, true);
#else
FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);
#endif
/* 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);
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_SetFDRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
#else
FLEXCAN_SetRxMbConfig(EXAMPLE_CAN, RX_MESSAGE_BUFFER_NUM, &mbConfig, true);
#endif
/* Setup Tx Message Buffer. */
#if (defined(USE_CANFD) && USE_CANFD)
FLEXCAN_SetFDTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#else
FLEXCAN_SetTxMbConfig(EXAMPLE_CAN, TX_MESSAGE_BUFFER_NUM, true);
#endif
if ((node_type == 'A') || (node_type == 'a'))
{
LOG_INFO("Press any key to trigger one-shot transmission\r\n\r\n");
frame.dataByte0 = 0;
}
else
{
LOG_INFO("Start to Wait data from Node A\r\n\r\n");
}
while (true)
{
if ((node_type == 'A') || (node_type == 'a'))
{
GETCHAR();
frame.id = FLEXCAN_ID_STD(txIdentifier);
frame.format = (uint8_t)kFLEXCAN_FrameFormatStandard;
frame.type = (uint8_t)kFLEXCAN_FrameTypeData;
frame.length = (uint8_t)DLC;
#if (defined(USE_CANFD) && USE_CANFD)
frame.brs = 1U;
frame.edl = 1U;
#endif
txXfer.mbIdx = (uint8_t)TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
(void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif
/* Wait until Rx MB full. */
while (!rxComplete)
{
};
rxComplete = false;
LOG_INFO("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);
LOG_INFO("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)
{
LOG_INFO("B has been waken up!\r\n\r\n");
}
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = (uint8_t)RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
(void)FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
(void)FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif
/* Wait until Rx receive full. */
while (!rxComplete)
{
};
rxComplete = false;
LOG_INFO("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;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
(void)FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
(void)FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif
while (!txComplete)
{
};
txComplete = false;
LOG_INFO("Wait Node A to trigger the next transmission!\r\n\r\n");
}
}
}
@Lukas_Frank You have copy pasted the same code twice.
At line 38:
#define EXAMPLE_CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
should it be '||' or '/' or something else?
Thanks
Hi
#define EXAMPLE_CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
The "/ /" may be a formatting error on the forum but it should be "/"
See chapter 1.12 in https://www.utasker.com/docs/iMX/i.MX_RT_1021_uTasker.pdf for details of the clocking, whereby the specific reference uses the configuration as on page 30.
I would however double check the CLOCK_GetFreq(kCLOCK_Usb1PllClk) since it may give 480MHz and not the correct 60MHz.
Note that the SDK uses "register value" for FLEXCAN_CLOCK_SOURCE_DIVIDE, which is 1 less than the actual divider value, which explains why a + 1u needs to be added.
At the end of the day it is just calculating the CAN_CLK_ROOT frequency based on the selected source being 60MHz from PLL3 (due to CAN_CLK_SEL setting), divided by the FlexCAN pre-scaler value CAN_CLK_PODF.
Regards
Mark