Is FlexCAN3 (CAN-FD) dependent on LPUART module clock?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Is FlexCAN3 (CAN-FD) dependent on LPUART module clock?

Jump to solution
2,227 Views
johnpulera
Contributor II

Hi,

For our iMXRT1064-based project, we are using the fsl_flexcan.c driver distributed with MCUXpresso SDK, and we notice that the FLEXCAN_Init() function hangs if we don’t previously initialize one of the LPUART instances. The location of the hang is in FLEXCAN_Init(), when it comes time to disable the module, set CTRL1.CLKSRC bit and then re-enable the module. When the module is disabled (MCR.MDIS = 1), the MCR.LPMACK bit never gets set to acknowledge low power mode so software hangs in the while loop:

static inline void FLEXCAN_Enable(CAN_Type *base, bool enable)
{
  if (enable)
  {
    base->MCR &= ~CAN_MCR_MDIS_MASK;

    /* Wait FlexCAN exit from low-power mode. */
    while (base->MCR & CAN_MCR_LPMACK_MASK)
    { }
  }

We find that FlexCAN initializes successfully only if at least one of the LPUART clocks is enabled (e.g., CCM_CCGR0.CG14=3 for lpuart2 clock). If none of the lpuart clocks is enabled, then the software hangs. This behavior we confirmed with the canfd interrupt_transfer example code using the iMXRT1064EVB.

Is this expected behavior? Is it required to have the lpuart clock enabled for FlexCAN peripheral (at least the FlexCAN3 CAN-FD peripheral) to function correctly?

Thanks,
John

Labels (1)
0 Kudos
1 Solution
1,978 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi John Pulera,

   Thank you very much for your post about this question.

   You are right, today, I also test the newest SDK with the canfd function, when I disable the lpuart clock, I also reproduce the problems, so I check it with our internal related department, it turns out it is a known bug.

There are two workarounds for this issue:

-- Set CAN_CLK_SEL to 0 or 1 for CAN clock selection.
Or,
-- If CAN_CLK_SEL is set to 2, then the CCM must open any of UART clock gate by configuring the CCM_CCGRx register.

In the near future, we will put this workaround in the errata.

Now, please use the above two workarounds to solve it.

Sorry for the inconvenience we bring you.

Have a great day,
Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

View solution in original post

0 Kudos
5 Replies
1,978 Views
johnpulera
Contributor II

Hi Kerry,

We are using FlexCAN3 peripheral at pins

GPIO_AD_B0_14 (FLEXCAN3_TX) and GPIO_AD_B0_15 (FLEXCAN3_RX)

Here is the pin IOMUX initialization:

void BOARD_InitCANPins(void) {
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux( IOMUXC_GPIO_AD_B0_14_FLEXCAN3_TX, 1U);
    IOMUXC_SetPinMux( IOMUXC_GPIO_AD_B0_15_FLEXCAN3_RX, 1U);
    IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B0_14_FLEXCAN3_TX, 0x10B0u);
    IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_B0_15_FLEXCAN3_RX, 0x10B0u);
}

We are not using LPUART (all the LPUART clocks are disabled in CGM), which is how we discovered the issue. But if one of the LPUART peripherals (doesn't matter which) is initialized, then the CAN successfully initializes. We simply enable an LPUART clock at the end of BOARD_BootClockRun( ) to workaround the issue rather than initialize the LPUART with the lpuart driver:

    CLOCK_EnableClock(kCLOCK_Lpuart1); 

Thanks,

John

0 Kudos
1,978 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi John Pulera,

  That's strange, please share your simple project which can reproduce the problem, I will check it on my side.

  You can delete all the other code, just leave the FlexCAN code, I will test it on my MIMXRT1064-EVK board.

Have a great day,
Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
1,978 Views
johnpulera
Contributor II

Hi Kerry,

The problem is reproducible with the can_fd\interrupt_transfer example in the MCUXpresso SDK 2.4.0 with slight modification to remove dependencies on the debug console and lpuart code--that way the lpuart peripheral remains uninitialized. I don't see how I can attach a file, so I've inserted the modification of the single file (SDK\boards\evkmimxrt1064\driver_examples\canfd\interrupt_transfer\flexcan_interrupt_transfer.c) that I made below. When the code executes, it hangs inside FLEXCAN_Enable() as I described.

Thanks,

John

/*
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

//#include "fsl_debug_console.h"
#include "fsl_flexcan.h"
#include "board.h"

#include "pin_mux.h"
#include "clock_config.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define EXAMPLE_CAN CAN3
#define USE_CANFD (1)
/*
* DWORD_IN_MB DLC BYTES_IN_MB Maximum MBs
* 2 8 kFLEXCAN_8BperMB 32
* 4 10 kFLEXCAN_16BperMB 21
* 8 13 kFLEXCAN_32BperMB 12
* 16 15 kFLEXCAN_64BperMB 7
*
* 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 DWORD_IN_MB (2)
#define DLC (8)
#define BYTES_IN_MB kFLEXCAN_8BperMB

/* Select 80M clock divided by USB1 PLL (480 MHz) as master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_SELECT (2U)
/* Clock divider for master flexcan clock source */
#define FLEXCAN_CLOCK_SOURCE_DIVIDER (0U)
/* Get frequency of flexcan clock */
#define EXAMPLE_CAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 6) / (FLEXCAN_CLOCK_SOURCE_DIVIDER + 1U))
#define RX_MESSAGE_BUFFER_NUM (9)
#define TX_MESSAGE_BUFFER_NUM (8)

/*******************************************************************************
* Prototypes
******************************************************************************/

/*******************************************************************************
* Variables
******************************************************************************/
flexcan_handle_t flexcanHandle;
volatile bool txComplete = false;
volatile bool rxComplete = 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 void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData)
{
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;

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_InitPins();
BOARD_BootClockRUN();
//BOARD_InitDebugConsole();

/*Clock setting for FLEXCAN*/
CLOCK_SetMux(kCLOCK_CanMux, FLEXCAN_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_CanDiv, FLEXCAN_CLOCK_SOURCE_DIVIDER);

//PRINTF("********* FLEXCAN Interrupt EXAMPLE *********\r\n");
//PRINTF(" Message format: Standard (11 bit id)\r\n");
//PRINTF(" Message buffer %d used for Rx.\r\n", RX_MESSAGE_BUFFER_NUM);
//PRINTF(" Message buffer %d used for Tx.\r\n", TX_MESSAGE_BUFFER_NUM);
//PRINTF(" Interrupt Mode: Enabled\r\n");
//PRINTF(" Operation Mode: TX and RX --> Normal\r\n");
//PRINTF("*********************************************\r\n\r\n");

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();
node_type = 'B';
//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_ClkSrcOsc;
* flexcanConfig.baudRate = 1000000U;
* flexcanConfig.baudRateFD = 2000000U;
* flexcanConfig.maxMbNum = 16;
* flexcanConfig.enableLoopBack = false;
* flexcanConfig.enableSelfWakeup = false;
* flexcanConfig.enableIndividMask = false;
* flexcanConfig.enableDoze = false;
* flexcanConfig.timingConfig = timingConfig;
*/
FLEXCAN_GetDefaultConfig(&flexcanConfig);

/* Init FlexCAN module. */
#if (!defined(FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE)) || !FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE
flexcanConfig.clkSrc = kFLEXCAN_ClkSrcPeri;
#else
#if defined(CAN_CTRL1_CLKSRC_MASK)
if (!FSL_FEATURE_FLEXCAN_INSTANCE_SUPPORT_ENGINE_CLK_SEL_REMOVEn(EXAMPLE_CAN))
{
flexcanConfig.clkSrc = kFLEXCAN_ClkSrcPeri;
}
#endif
#endif /* FSL_FEATURE_FLEXCAN_SUPPORT_ENGINE_CLK_SEL_REMOVE */
/* 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_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'))
{
//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 (1)
{
if ((node_type == 'A') || (node_type == 'a'))
{
//GETCHAR();
frame.id = FLEXCAN_ID_STD(txIdentifier);
frame.format = kFLEXCAN_FrameFormatStandard;
frame.type = kFLEXCAN_FrameTypeData;
frame.length = DLC;
#if (defined(USE_CANFD) && USE_CANFD)
frame.brs = 1;
#endif
txXfer.mbIdx = TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
txXfer.framefd = &frame;
FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif

while (!txComplete)
{
};
txComplete = false;

/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif

/* Wait until Rx MB 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);
//PRINTF("Press any key to trigger the next transmission!\r\n\r\n");
frame.dataByte0++;
frame.dataByte1=0x55;
}
else
{
/* Start receive data through Rx Message Buffer. */
rxXfer.mbIdx = RX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
rxXfer.framefd = &frame;
FLEXCAN_TransferFDReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#else
rxXfer.frame = &frame;
FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);
#endif

/* 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 = TX_MESSAGE_BUFFER_NUM;
#if (defined(USE_CANFD) && USE_CANFD)
frame.brs = 1;
txXfer.framefd = &frame;
FLEXCAN_TransferFDSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#else
txXfer.frame = &frame;
FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
#endif

while (!txComplete)
{
};
txComplete = false;
//PRINTF("Wait Node A to trigger the next transmission!\r\n\r\n");
}
}
}

0 Kudos
1,979 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi John Pulera,

   Thank you very much for your post about this question.

   You are right, today, I also test the newest SDK with the canfd function, when I disable the lpuart clock, I also reproduce the problems, so I check it with our internal related department, it turns out it is a known bug.

There are two workarounds for this issue:

-- Set CAN_CLK_SEL to 0 or 1 for CAN clock selection.
Or,
-- If CAN_CLK_SEL is set to 2, then the CCM must open any of UART clock gate by configuring the CCM_CCGRx register.

In the near future, we will put this workaround in the errata.

Now, please use the above two workarounds to solve it.

Sorry for the inconvenience we bring you.

Have a great day,
Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos
1,978 Views
kerryzhou
NXP TechSupport
NXP TechSupport

HI John Pulera ,

Could you please also tell me the detail pins for FlexCan and the LPUART you are using?

Have a great day,
Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos