Colibri iMX8 CAN on M4

Hello community,

I want to use 2 flexCAN devices on Colibri iMX8QXP.
First should be used from M4 (freertos) and second from A35 (linux).
We’ve got own carrier board and already tested both CAN devices are usable from linux and they’re working great.

For the M4 I looked on example flexcan/interrupt_transfer and bumped on issues which leads to HardFault_handler in freertos.

It looks that we’ve got problem in device tree, bacause when I do not boot linux in u-boot, CAN from M4 is working well. During the linux booting I got HardFault_handler in M4. So this leads me to bad usage of something in linux part…

We’re using flexcan1 (pins 32/34) and flexcan2 (pins 55/63), flexcan1 is used by M4.
Updating device tree is done in u-boot - completely removing flexcan1 node:

fdt rm /can@5a8d0000

We use this even for lpuarts to have debug console out from M4 and it works perfectly.

[Update] Just figured out that if I remove both CAN devices from device-tree, I can boot linux and CAN from M4 works well

fdt rm /can@5a8e0000 && fdt rm /can@5a8d0000

[Update] We’re using BSP 3.0.4 / 4 (we couldn’t update to higher version on v1.0B). Found some problems in device-tree which are corrected in BSP 5. Also figured out, that all flexcan devices uses the same clocks. Suppose that this should be the problem. Are we able to set clock only once for all devices? And from each of CPUs? E.g. when M4 boots, set it there and linux wouldn’t set it then. But when M4 doesn’t boot, set clocks during linux boot?

So my questions are:

  1. Is this even possible - to use one flexcan from linux and second one from M4?
  2. What should I edit in device-tree to make this work?

I have already read some questions here mentioning pinmux & clock settings.
Should I change something in device-tree or use something else than was used in the example for M4?

Thank You.

Kind regards

Hi @slezak.martin ,

did you add clk_ignore_unused to u-boot’s defargs variable?

Tried, didn’t work

Are you using RPMSG to communicate M4. I would try initializing M4 CAN by RPMSG command. Though of course it would be useful to see real cause of issue.

I wonder whether fdt rm supports partial addresses or not? fdt rm by full address like /soc/apb@xxx/bus@xxx/etc certainly work. When not clear from dst and dtsi files, one may check it loading fdt to memory and listing fdt contents with fdt list or fdt print. Removing by module alias, which is specified in aliases {} in your DT, works as well. But something like /can@5a8e0000? Certainly you don’t have anything like this in the root / of device tree. But I see && in your fdt_fixup. Hm, if it failed then it would break after first one.

Yes, we’re using RPMSG, but, let’s say, we want start communication before linux boots.

fdt rm works as expected, it removes both cans, M4 then works correctly with CAN.
My current fdt_fixup is setenv fdt_fixup 'echo Fixing FDT - UART_D(1) + FLEXCAN 1,2 && fdt addr ${fdt_addr_r} && fdt rm /serial@5a070000 && fdt rm /can@5a8e0000 && fdt rm /can@5a8d0000' and removes also UART for debug console… No kernel panic, M4 prints into this UART, so I assume it works as expected.

We could still open 2 devices on M4 and use RPMSG to communicate with 2nd CAN from linux, but it would be great to use it directly.

Hi @slezak.martin ,

I respect you want M4 comms to start before Linux. But in case kernel driver toggles and flips too much in CAN clock settings or something, triggering start of M4 CAN setup after kernel does its bad job, would give you working both, M4 and Linux. Of course it would be the best to find the root and fix it.

(Thanks for your way for fdt rm. It’s somewhat scary, I see great chances to rm something without intention, I’ll learn it more when time permits)

Oh, it’s CAN FD and 40 or more MHz module clock from some PLL? This where Linux may disturb you or hurt itself. Could you try setting up M4 CAN to be clocked directly from oscillator clock, no PLL?

Hi @slezak.martin,

Can you please confirm which version of Colibri iMX8XQXP are you using?

Reading your text, I can conclude that it is V1.0B, I’m sorry to inform you that we don’t provide support for it anymore, as it was in Early Access stage.

We strongly suggest you to purchase the V1.0D version of Colibri iMX8XQXP.

About the BSP, we recommend to use the BSP 5.1.0, that is now on Production Release.

About the FreeRTOS, did you get it from the NXP MCUXpresso for “MIMX8QX6xxxFZ”?

Considering the SDK 2.9.0 from NXP, I did a quick check here and I realized that it’s already set for FlexCAN0 (pins 32 and 34, as you saw). See for example the sample project at driver_examples/flexcan/loopback. Then, in the pin_mux.h

/* FLEXCAN0_RX (coord Y34), BB_CAN0_RX/J13C[25] */
#define BOARD_INITPINS_BB_CAN0_RX_PERIPHERAL                      ADMA__FLEXCAN0   /*!< Device name: ADMA__FLEXCAN0 */
#define BOARD_INITPINS_BB_CAN0_RX_SIGNAL                              flexcan_rx   /*!< ADMA__FLEXCAN0 signal: flexcan_rx */
#define BOARD_INITPINS_BB_CAN0_RX_PIN_NAME                           FLEXCAN0_RX   /*!< Pin name */
#define BOARD_INITPINS_BB_CAN0_RX_PIN_FUNCTION_ID               SC_P_FLEXCAN0_RX   /*!< Pin function id */
#define BOARD_INITPINS_BB_CAN0_RX_LABEL                    "BB_CAN0_RX/J13C[25]"   /*!< Label */
#define BOARD_INITPINS_BB_CAN0_RX_NAME                              "BB_CAN0_RX"   /*!< Identifier name */

/* FLEXCAN0_TX (coord Y32), BB_CAN0_TX/J13C[26] */
#define BOARD_INITPINS_BB_CAN0_TX_PERIPHERAL                      ADMA__FLEXCAN0   /*!< Device name: ADMA__FLEXCAN0 */
#define BOARD_INITPINS_BB_CAN0_TX_SIGNAL                              flexcan_tx   /*!< ADMA__FLEXCAN0 signal: flexcan_tx */
#define BOARD_INITPINS_BB_CAN0_TX_PIN_NAME                           FLEXCAN0_TX   /*!< Pin name */
#define BOARD_INITPINS_BB_CAN0_TX_PIN_FUNCTION_ID               SC_P_FLEXCAN0_TX   /*!< Pin function id */
#define BOARD_INITPINS_BB_CAN0_TX_LABEL                    "BB_CAN0_TX/J13C[26]"   /*!< Label */
#define BOARD_INITPINS_BB_CAN0_TX_NAME                              "BB_CAN0_TX"   /*!< Identifier name */

To keep the FlexCAN0 in M4, you shall disable the UART_B interface, because it uses FlexCAN0 pins. See:

Analyzing your topics in advance:

- Is this even possible - to use one flexcan from linux and second one from M4?

R: Yes, it’s possible, because they are different CAN Controllers each.

- What should I edit in device-tree to make this work?

R: That depends on the FlexCAN interface you want to allocate to the M4 core. Depending on that, you need to remove on the device-tree all the pins, muxings and related items to the CAN interface you want to allocate for M4.

Also, this is an observation for the FlexCAN you want to keep on Linux. You’ll have to disable the default interface making use of its signals. See the CAN Signal pins from Colibri iMX8X Datasheet:

Best regards,
André Curvello


it’s been a while and I still don’t know how to use CAN on linux an M4.
I exchanged some mails with Andre Curvello.
Last one is on 27.4.2021 and where he asked Gustavo_Leal to analyze issue (see quotes below).
I tried to reach both of them via email but Andre Curvello’s mail wasn’t found at and Gustovo hasn’t replied yet…
Can somebody help me out?

Hi Martin,

That’s weird.

@Gustavo Leal, can you analyze this issue? What can you tell about it?

Best regards,

André Curvello

He answered for my last update:

Hello Andre,

I finally finished our linux image with new BSP 5.2.
So I tried use flexcan from M4 and linux.
It kind of works, but only when i start receiving in M4 after setting CANbus link up in linux.
Up to now I figured out, that booting kernel - even with removed both used CANbus peripheries - sets CANbus to Low Power mode.

When I initialize flexcan in M4, power mode gives SC_PM_PW_MODE_ON.
During booting of linux it switches to SC_PM_PW_MODE_LP.

I also tried to switch for new MCUxpresso SDK - from 2.7.0 to 2.9.0 but the results are same.

When I start listening on M4 CANbus before I set link in linux up, I finish in HardFault handler on M4.
When I start listeningn on M4 CANbus after I set link in linux up, it works as expected.

Is there any way to disable setting, let’s say missing devices, into LP mode? E.g. in device-tree?