Split CAN1 for SPE and CAN0 for Linux

I’m trying to send from my CAN1 interface to CAN0 that is mapped into Linux. I’ve modified the can-app.c to only tx on CAN1. Next, I went through carefully and status=“disabled” all the mttcan related entries in all the tegra186 dts files I could find.

Once both linux and spe are built and flashed, my tx2 hangs. The linux serial console show that it stops at:
NOTICE: BL31: v1.3(release):5b49e7f80
NOTICE: BL31: Built : 08:38:54, Feb 19 2021
ipc-unittest-main: 1519: Welcome to IPC unittest!!!
ipc-unittest-main: 1531: waiting forever
ipc-unittest-srv: 329: Init unittest services!!!
hwkey-agent: 40: hwkey-agent is running!!
hwkey-agent: 197: key_mgnt_processing …
hwkey-agent: 189: Setting EKB key 0 to slot 14
hwkey-agent: 167: Init hweky-agent services!!
luks-srv: 40: luks-srv is running!!
luks-srv: 157: Init luks-srv IPC services!!
platform_bootstrap_epilog: trusty bootstrap complete

I’ve tried to be careful in disablin can1 in the linux dts files but am stuck.
When can_app_tx_task_init(NULL) the tx2 boots fine. When can_app_tx_task_init(CAN1_CONTROLLER) it hangs.

Any ideas how to get past this? Are can0 and can1 MUST be oriented to either spe or linux together?

Edit: I specifically disabled dts entries like mttcan@c320000 and made sure mttcan@c310000 were set to okay.


It seems the IRQ line is shared by both canX “ports” ?? I noticed that the spe mttcan code uses irq 0 and the linux is set for tegra_aon_gpio which has an irq 0? Are both of these contending for the same line?

Can an irq for the spe be changed? I’m looking at the schematics trying to figure this out…


hello timothyj_75080,

could you please check the steps as following to enable and check CAN on Jetson TX2.
for example, How to use Vector CAN analyzer in Jetson TX2 - #2 by spatra

It seems that the SoC on the TX2 does not allow different “hosts” (SPE and Linux host) to control each can port independently?

The on-chip CAN controller only allows one “host” at a time to operate can port (ie can0 and can1)???

Thanks for your help!!

Looking at the TRM, it lists two can controllers… Does this mean, in theory, that additional can ports can be created say can2 and can3…

Or, does “two can controllers” mean that only two ports are (a can0 and can1) be supported??

Thanks so much!!

hello curiousdev,

please also access L4T Driver Package (BSP) Sources, and refer to device tree sources,
for example,
there’re two CAN controller device tree bindings,

mttcan0: mttcan@c310000 {...}
mttcan1: mttcan@c320000 {...}

Yes, am familiar with those entries. I changed the status for c310000 to be okay and c320000 to be disabled. In the SPE code, I disabled the CAN0_CONTROLLER and used the CAN1_CONTROLLER as a transmit in the can-app.c code.

I thought a candump of can0 would see the incoming messages from the SPE CAN1 but the tx2 hangs on boot. Could the SPE and Linux be contending for resources or something?


hello curiousdev,

please check the modification form user-space,
for example, $ cat /proc/device-tree/mttcan\@c310000/status

you may also load the CAN kernel drivers,
1.Insert the CAN BUS subsystem support module, $ modprobe can
2.Insert the raw CAN protocol module (CAN-ID filtering), $ modprobe can_raw
3.Add real CAN interface support (for Jetson, mttcan), $ modprobe mttcan

after that, set the interface properties for transferring packets (i.e. cansend) for testing.
for example,
$ ip link set can0 up type can bitrate 500000 dbitrate 1000000 berr-reporting on fd on

Hi Curiousdev,

Try below steps and let me know if it still hangs at the boot. I am assuming CAN0 is accessed from SPE and CAN1 is from Linux ( no strict requirement, just for explanation purposes)

  1. Please download the latest SPE source code versioned 32.5 from Jetson Download Center | NVIDIA Developer.
  2. Modify soc/t18x/target_specific.mk to enabled CAN app and CAN TX controller by setting ENABLE_CAN_TX := 1 and ENABLE_CAN_APP:= 1
  3. Similarly open app/can-app.c and define #define ENABLE_CAN0_AS_TX while commenting out CAN1 related defines.
  4. Open app/can-app-tx-task.c and add below line right after fd.payload.frame.data[1] = 0x55;
    vTaskDelay(CAN_TEST_DELAY * 4);
    4.a This step waits for the linux side to boot for the 40 seconds, you can change the wait timeout as needed.
    4.b Also app/can-app-tx-task.c sends 6 types of CAN frames in the while loop, make sure to comment out the unwanted format can_test_transmit.
  5. Compile spe binary and flash

Above steps makes CAN0 from SPE to act as transmitter and disables CAN1 access from SPE.

From the linux side, follow regular steps as you did previously.

I believe this should ungate you at least about the hang part. I am trying full validation my side, will update.