FlexCan CAN_MCR_LPM_ACK bit not set

Hello everyone,

This problem happens when running the flexcan_network example.

When FLEXCAN_Init is called, it executes FLEXCAN_Disable. In this function, the while loop while (!(CAN_MCR_REG(base) & CAN_MCR_LPM_ACK_MASK)); will be stuck forever. This is because for some reason the LPM_ACK bit will never be set in the MCR register. It seems unlikely that the module is still waiting for a message, as this is still in the initialization phase.

When i remove this FLEXCAN_Disable the FLEXCAN_Init executes correctly, however the BOARD_FLEXCAN_HANDLER will never be called, which i think means that the transmit interrupt is not generated. I have no idea why this could be though.

The flexcan1 Rx and Tx are connected to a mcp2562, but when measuring with a scope, no output can be seen from here.

Does anyone know how this could be fixed?

Thanks in advance!

Hm, reading the description of the LPM_ACK it seems that FlexCAN stays in some low power/stop mode. However, unless IOMUXC_GPR_GPR4 is set, the peripheral should not go into low power mode. Can you check that register?

What I would check first is whether your CAN bus is properly setup. CAN usually checks if the bus has a proper state, and it might be that FlexCAN does not startup properly if the state is not proper. Do you have the CAN transceiver connected to a properly terminated CAN bus?

To check whether it is software or hardware, I would recommend try using FlexCAN from Linux. See also this article.

Otherwise it might be also worth trying with our Colibri Evaluation Board, which has a can transceiver on board and is known to work with the Colibri iMX7.

Hm, reading the description of the
LPM_ACK it seems that FlexCAN stays in
some low power/stop mode. However,
unless IOMUXC_GPR_GPR4 is set, the
peripheral should not go into low
power mode. Can you check that
register?

It actually is supposed to go into low power mode, because the FLEXCAN_Disable sets the MDIS bit which will disable the Flexcan module. However for some reason this is not happening, which is why the LDM_ACK bit is not set and the program will stay stuck in this (while (!(CAN_MCR_REG(base) & CAN_MCR_LPM_ACK_MASK))) while loop. The IOMUXC_GPR_GPR4 register only has either the CPU_ STANDBYWFE bit set, the CPU_ STANDBYWFI bit set or both those bits set. However these bits are for the A7 core 1 and 2 low power states.

Regarding the setup of the CAN bus, i’m using the flexcan_network example. Perhaps you could see if this example is working for you, to verify the setup used in that example is correct.

Besides that the CAN bus network i’m using is properly terminated, and has worked with other boards before.

Tested it on my side and I could reproduce the issue. Testing with Linux seems to work fine, so I knew it must been something with how the M4 firmware setup CAN.

In the end it turns out that pin muxing for FlexCAN1 was still slightly off: Mux mode needs to be 1 and daisy chaining for RX pin was missing/wrong. With that, the M4 firmware started sending frames about ~1sec, which I was able to receive from a Linux machine like this:

$ sudo ip link set can0 type can bitrate 125000
$ sudo ip link set up dev can0 
$ sudo candump can0
  can0  123   [1]  00
  can0  123   [1]  01
  can0  123   [1]  02
  can0  123   [1]  03
  can0  123   [1]  04
  can0  123   [1]  05
  can0  123   [1]  06
  can0  123   [1]  07
  can0  123   [1]  08
 ....

I pushed the fixed pin muxing to our colibri-imx7-m4-freertos-v8 branch.

Thanks for the response!

I recompiled the flexcan_network example with a fresh download from the git repository where you added the fix and tried to run it. However i still get the same issue, that it is stuck in the while loop while checking for the LPM_ACK bit.

When you tried to reproduce the issue, did you use the Aster carrier board, or did you use a different board?

For my testing I used the Colibri Evaluation Board V3.2B. I reused the on-board CAN transceiver by connecting SODIMM_55 to JP4 (CAN_TX) and SODIMM_63 to JP5 (CAN RX). I connected the board via a DB-9 cable with proper CAN termination to a PCAN-USB adapter.

But even if I leave the SODIMM 55/63 open (floating) on the carrier board, initialization seems to succeed now.

To rule out any compile/fetch issue, you can try my binary. Using this flexcan_network.elf I see after the usual prints my additionally added “FlexCAN done” and “GPT done” prints.

Thanks for sending that binary!

Sadly i still only get up to NODE is 1 and after that it won’t print anything.

Based on what you said about leaving the CAN_TX and CAN_RX floating, the problem can’t be the CAN network either if i’m correct.

Is there anything else that could be going wrong here?

Still can be the network, when one of the pins are not in a default state (driven low). Can you test with leaving them floating too?

With every update/fix that you currently provided i tried both leaving the Rx and Tx pin floating, and connecting it to the CAN network, however in none of the setups did it work, sadly.

I can reproduce the issue on a Viola. The issue is that SODIMM 55 and 63 are connected through a Auto Direction Sensing Level Shifter (FXMA108). This seems not to play well with CAN.

You can use a pull-up on SODIMM 63 to define the state on the level shifters output side. With that initialization worked for me.

To get to SODIMM 55/63 unencumbered I would recommend using a different Carrier Board.

Alternatively, you can try using SODIMM 81/94, which are directly available on X20. You need to use FlexCAN2 then, and alter the pinmux in the firmware.

I used the above for the pinmux of flexCAN2 and connected X20-pin29 (CAN Rx) and X20-pin31 (CAN Tx) to the CAN tranciever. Sadly i get the same results, it won’t pass the while loop for the LPM_ACK bit.

I also tried this with floating Rx and Tx which gave me the exact same result.

You need to use for CAN2_TX and CAN2_RX ...MUX_MODE(**2**);.

You also need to take care of daisy chaining. The RX pins need beside the mux, a input selection. Since you mux CAN2_RX on the I2C3_SCL pad, it needs to be set to 1:

IOMUXC_FLEXCAN2_RX_SELECT_INPUT = 0x1;

For this kind of information you want to check the i.MX 7Dual Reference Manual available here. That particular information you can find in chapter 8.2.7.308 FLEXCAN2_RX_SELECT_INPUT DAISY Register.

Thanks for this solution, it goes through with the initialization now!

However a new problem has come up now, the interrupt is not called when sending a message. I will post a new question for this problem.