i.MX6UL FlexCAN Kernel Panic with Transceiver in Standby and Transmit Attempted

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

i.MX6UL FlexCAN Kernel Panic with Transceiver in Standby and Transmit Attempted

Jump to solution
3,473 Views
compmas2
Contributor V

I am working with a custom i.MX6UL based board using the FlexCAN driver for CAN on both the imx_3.14.38_6ul_ga with 9x9_patch and imx_3.14.52_1.1.0_ga kernels.  The problem I am encountering is when the CAN transceiver is placed into Standby mode and I try to transmit a message, I get a kernel panic.

I am initializing both SocketCAN interfaces using the following commands:

/sbin/ip link set can0 type can restart-ms 100

/sbin/ip link set can0 up type can bitrate 250000

/sbin/ifconfig can0 txqueuelen 1000

/sbin/ip link set can1 type can restart-ms 100

/sbin/ip link set can1 up type can bitrate 250000

/sbin/ifconfig can1 txqueuelen 1000

The CAN transceivers are hard wired on, so I did not configure a xceiver-supply in the boards .dts file.  Here are the relevant sections of the custom board's .dts file for CAN:

&flexcan1 {

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_flexcan1>;

        status = "okay";

};

&flexcan2 {

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_flexcan2>;

        status = "okay";

};

pinctrl_flexcan1: flexcan1grp{

     fsl,pins = <

          MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX      0x1f0b0 /* MPU_CAN1_RXD */

          MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX      0x1f0b0 /* MPU_CAN1_TXD */

     >;

};

pinctrl_flexcan2: flexcan2grp{

     fsl,pins = <

          MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX      0x1f0b0 /* MPU_CAN2_RXD */

          MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX      0x1f0b0 /* MPU_CAN2_TXD */

     >;

};

Here is the kernel panic output I get when I attempt to send a message using cansend:

# cansend can0 500#11.22.33.44

# BUG: scheduling while atomic: swapper/0/0x00000100

Unable to handle kernel NULL pointer dereference at virtual address 00000000

pgd = 80004000

[00000000] *pgd=00000000

Internal error: Oops: 80000007 [#1] ARM

Modules linked in:

CPU: 0 PID: 0 Comm: swapper Not tainted 3.14.52 #1

task: 807e9ca0 ti: 807de000 task.ti: 807de000

PC is at 0x0

LR is at try_to_wake_up+0x48/0xf8

pc : [<00000000>]    lr : [<8004d09c>]    psr: 00070193

sp : 807dfb88  ip : 00000015  fp : 807dfb9c

r10: 807f1018  r9 : 00000003  r8 : 00000001

r7 : 00000004  r6 : 2bcbbd04  r5 : 60070193  r4 : 807e9ca0

r3 : 00000000  r2 : 00000001  r1 : 807e9ca0  r0 : 807f1460

Flags: nzcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment kernel

Control: 10c53c7d  Table: 87924059  DAC: 00000015

Process swapper (pid: 0, stack limit = 0x807de230)

Stack: (0x807dfb88 to 0x807e0000)

fb80:                   807dfde8 807f1048 807dfde8 807f1048 807f1018 80047f34

fba0: 80047f14 80048254 00000000 807f1018 00000000 80048994 ffffffff 7fffffff

fbc0: 2bcbbd04 00000004 00000000 00000000 ffffffff 7fffffff 2bcbbd04 00000004

fbe0: 2bcbbd04 00000004 00000010 00000001 00000057 00000000 00000000 00000057

fc00: 84008b80 8082bad2 00000000 8001aafc 807ebd80 800588f8 00000000 8082b050

fc20: 84008b80 00000057 807dff68 f4a02000 80831486 00000006 00000000 800589e8

fc40: 84008b80 8005b100 00000057 800580d8 807fb2f4 8000e9c8 f4a0200c 807e6424

fc60: 807dfc80 80008550 00000000 80056a84 60070113 ffffffff 807dfcb4 80011ac0

fc80: 00000001 807f1bec 807f2844 60070113 00000032 807f1b88 00000000 00000000

fca0: 80831486 00000006 00000000 00000000 00000000 807dfcc8 00000000 80056a84

fcc0: 60070113 ffffffff 00000000 00000000 00000000 00000000 80831486 00000032

fce0: 60070113 00000000 00000000 00000001 00000003 00000000 807e9ca0 807f1460

fd00: 807f1460 807de010 8082ebc0 8082bacf 807dfd4c 80599d78 806c6cf0 807dfd34

fd20: 00000001 807dfd34 00000000 8004beb0 806c6cf0 807e9ee0 00000000 00000100

fd40: 00000002 807de018 807dfdd4 8059e0bc c1103780 2b864677 807f1048 2b864677

fd60: 00000004 80065e70 00000000 2b85f857 00000004 807f1018 807f1048 80048738

fd80: 00002710 00000000 ffffffff 00000000 2b864677 00000004 80872140 807de018

fda0: 00000001 00004e20 00000000 00002710 8082ebc0 807de018 00000001 00004e20

fdc0: 00000000 00002710 8082ebc0 8082ea44 8082ea40 8059dbf4 00002710 00000001

fde0: 00004e20 00000000 807dfde8 00000000 00000000 00000000 2b864677 00000004

fe00: 2b861f67 00000004 80047f14 807f1048 00000002 00000000 00000000 807f0710

fe20: 87990280 00000002 8419e800 88988000 00000004 807e6040 8082ebc0 80036084

fe40: 00002710 00000000 88988000 8033d8e8 00000001 8419e800 8419e800 807de000

fe60: 00000100 8033a640 8082ebc0 8082ea44 8082ea40 8033de54 00000001 8419e800

fe80: 00000000 8033a6d4 807de000 879902c8 807dfea0 807de020 00000000 800365ec

fea0: 2b940b34 00000004 807dfec0 00000000 00200200 807f0710 8082f3d0 80036774

fec0: 807dfec0 807dfec0 00015200 40000001 00000000 00000100 00000001 807de028

fee0: 807de000 800311b4 00000001 00015200 8082ea40 807f1928 8082ea00 0000000a

ff00: 805a25b8 ffff91d0 807f0710 00200000 00000000 807de038 00000057 00000000

ff20: f4a02000 8082bad0 807de000 00000000 00000000 80031514 807fb2f4 8000e9cc

ff40: f4a0200c 807e6424 807dff68 80008550 8000eb84 8000eb88 60070013 ffffffff

ff60: 807dff9c 80011ac0 00000000 807f1f70 00000000 80019fe0 807de000 807e60e8

ff80: 807de038 8082bad0 8082bad0 807de000 00000000 00000000 01000000 807dffb0

ffa0: 8000eb84 8000eb88 60070013 ffffffff 807f1f70 80058060 ffffffff 807909ec

ffc0: ffffffff ffffffff 80790500 00000000 00000000 807d559c 00000000 10c53c7d

ffe0: 807e6070 807d5598 807eadc0 80004059 410fc075 80008070 00000000 00000000

[<8004d09c>] (try_to_wake_up) from [<80047f34>] (hrtimer_wakeup+0x20/0x28)

[<80047f34>] (hrtimer_wakeup) from [<80048254>] (__run_hrtimer.isra.35+0x38/0xdc)

[<80048254>] (__run_hrtimer.isra.35) from [<80048994>] (hrtimer_interrupt+0xf0/0x294)

[<80048994>] (hrtimer_interrupt) from [<8001aafc>] (mxc_timer_interrupt+0x2c/0x34)

[<8001aafc>] (mxc_timer_interrupt) from [<800588f8>] (handle_irq_event_percpu+0xd0/0x198)

[<800588f8>] (handle_irq_event_percpu) from [<800589e8>] (handle_irq_event+0x28/0x38)

[<800589e8>] (handle_irq_event) from [<8005b100>] (handle_fasteoi_irq+0x70/0x130)

[<8005b100>] (handle_fasteoi_irq) from [<800580d8>] (generic_handle_irq+0x2c/0x3c)

[<800580d8>] (generic_handle_irq) from [<8000e9c8>] (handle_IRQ+0x38/0x84)

[<8000e9c8>] (handle_IRQ) from [<80008550>] (gic_handle_irq+0x2c/0x54)

[<80008550>] (gic_handle_irq) from [<80011ac0>] (__irq_svc+0x40/0x50)

Exception stack(0x807dfc80 to 0x807dfcc8)

fc80: 00000001 807f1bec 807f2844 60070113 00000032 807f1b88 00000000 00000000

fca0: 80831486 00000006 00000000 00000000 00000000 807dfcc8 00000000 80056a84

fcc0: 60070113 ffffffff

[<80011ac0>] (__irq_svc) from [<80056a84>] (vprintk_emit+0x150/0x418)

[<80056a84>] (vprintk_emit) from [<80599d78>] (printk+0x34/0x44)

[<80599d78>] (printk) from [<8004beb0>] (__schedule_bug+0x44/0x64)

[<8004beb0>] (__schedule_bug) from [<8059e0bc>] (__schedule+0x31c/0x3d4)

[<8059e0bc>] (__schedule) from [<8059dbf4>] (schedule_hrtimeout_range_clock+0xb4/0x140)

[<8059dbf4>] (schedule_hrtimeout_range_clock) from [<80036084>] (usleep_range+0x48/0x50)

[<80036084>] (usleep_range) from [<8033d8e8>] (flexcan_chip_start+0x64/0x3ac)

[<8033d8e8>] (flexcan_chip_start) from [<8033de54>] (flexcan_set_mode+0x14/0x60)

[<8033de54>] (flexcan_set_mode) from [<8033a6d4>] (can_restart+0x94/0xc8)

[<8033a6d4>] (can_restart) from [<800365ec>] (call_timer_fn.isra.42+0x24/0x88)

[<800365ec>] (call_timer_fn.isra.42) from [<80036774>] (run_timer_softirq+0x124/0x198)

[<80036774>] (run_timer_softirq) from [<800311b4>] (__do_softirq+0x114/0x21c)

[<800311b4>] (__do_softirq) from [<80031514>] (irq_exit+0xa8/0xf0)

[<80031514>] (irq_exit) from [<8000e9cc>] (handle_IRQ+0x3c/0x84)

[<8000e9cc>] (handle_IRQ) from [<80008550>] (gic_handle_irq+0x2c/0x54)

[<80008550>] (gic_handle_irq) from [<80011ac0>] (__irq_svc+0x40/0x50)

Exception stack(0x807dff68 to 0x807dffb0)

ff60:                   00000000 807f1f70 00000000 80019fe0 807de000 807e60e8

ff80: 807de038 8082bad0 8082bad0 807de000 00000000 00000000 01000000 807dffb0

ffa0: 8000eb84 8000eb88 60070013 ffffffff

[<80011ac0>] (__irq_svc) from [<8000eb88>] (arch_cpu_idle+0x38/0x3c)

[<8000eb88>] (arch_cpu_idle) from [<80058060>] (cpu_startup_entry+0xb8/0xf4)

[<80058060>] (cpu_startup_entry) from [<807909ec>] (start_kernel+0x2bc/0x2c8)

Code: bad PC value

---[ end trace 0dc1441ba4a64f46 ]---

Kernel panic - not syncing: Fatal exception in interrupt

Rebooting in 1 seconds..

mxc_restart: Watchdog reset failed to assert reset

I have verified the existence of this problem on the i.MX6UL EVK board too with the exact same kernel panic details using the imx6ul-14x14-evk.dts device tree. I first verified the CAN was working correctly with CAN Standby low.  Then by running the following commands I put the CAN transceiver into standy, sent a message, and caused the kernel panic:

echo 251 > /sys/class/gpio/export

echo 1 > /sys/class/gpio/gpio251/value

cansend can0 500#11.22.33.44

Best Regards,

Matthew Starr

Labels (3)
0 Kudos
Reply
1 Solution
2,147 Views
fabio_estevam
NXP Employee
NXP Employee

Hi Matthew,

Does this help?

--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -340,7 +340,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
                return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
                return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(100, 200);
+               udelay(200);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
                return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
                return -ETIMEDOUT;
@@ -412,7 +412,7 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)

        flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
                return -ETIMEDOUT;

--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -340,7 +340,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
                return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
                return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(100, 200);
+               udelay(200);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
                return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
                return -ETIMEDOUT;
@@ -412,7 +412,7 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)

        flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
                return -ETIMEDOUT;

View solution in original post

0 Kudos
Reply
7 Replies
2,148 Views
fabio_estevam
NXP Employee
NXP Employee

Hi Matthew,

Does this help?

--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -340,7 +340,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
                return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
                return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(100, 200);
+               udelay(200);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
                return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
                return -ETIMEDOUT;
@@ -412,7 +412,7 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)

        flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
                return -ETIMEDOUT;

--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -340,7 +340,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
                return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
                return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && !(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(100, 200);
+               udelay(200);

        if (!(flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
                return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
        flexcan_write(reg, &regs->mcr);

        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK)
                return -ETIMEDOUT;
@@ -412,7 +412,7 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)

        flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
        while (timeout-- && (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST))
-               usleep_range(10, 20);
+               udelay(20);

        if (flexcan_read(&regs->mcr) & FLEXCAN_MCR_SOFTRST)
                return -ETIMEDOUT;

0 Kudos
Reply
2,147 Views
compmas2
Contributor V

Fabio,

That fixed the issue. Now each time I try to transmit CAN messages using cansend when the CAN stanby is enabled, it just prints the following:

flexcan 2090000.can can0: writing ctrl=0x0729a055

IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready

I am able to successfully disable CAN standby and can transmit messages again without a kernel panic.

Regards,

Matthew Starr

0 Kudos
Reply
2,147 Views
alejandrolozan1
NXP Employee
NXP Employee

Hi Fabio,

Were you able to reproduce the problem? I was not.

Regards,

Alejandro

0 Kudos
Reply
2,147 Views
alejandrolozan1
NXP Employee
NXP Employee

Hi Matthew,

Let me try that out on my side. But is there a specific reason of trying to send a can message when the transciever is in standby mode?

Best Regards,

Alejandro

0 Kudos
Reply
2,147 Views
compmas2
Contributor V

When using CAN as a wakeup source to come out of standby, there are two situations where this could be a problem when multiple applications are using SocketCAN and only one can control the CAN transceiver standby pin:

  • When going into suspend an application might still be sending CAN messages through SocketCAN after the CAN transceiver standby pin has been set.
  • When coming out of standby, an application using SocketCAN could start transmitting messages on the CAN bus again before the CAN transceiver standby pin has been unset.

A synchronization method could be used between multiple applications using SocketCAN to stop and resume communication, but really shouldn't be needed to avoid a kernel panic.  This also limits portability of the applications using SocketCAN to other Linux based products that don't have this issue.

0 Kudos
Reply
2,147 Views
alejandrolozan1
NXP Employee
NXP Employee

Hi,

I have tried to replicate the problem on the imx6ul-evk, but with the commands you mention I get the below errors:

/sbin/ip link set can0 type can restart-ms 100

ip: either "dev" is duplicate, or "type" is garbage

I am using L3.14.52. Besides the EVK uses a I/O expander via SPI. I wonder how you mappef the /sys/gpio to the expander to disable the xceivers?

Best Regards,

Alejandro

0 Kudos
Reply
2,147 Views
compmas2
Contributor V

Alejandro,

It looks like you are using the busybox version of the 'ip' command and not the one provided as part of iproute2. That is why you are getting the "ip: either "dev" is duplicate, or "type" is garbage" error.

I am accessing the I/O expander GPIO pin for CAN standby with the commands at the end of my original message. Here are the commands from that message (assuming the GPIO sysfs interface is enabled in the kernel .config):

echo 251 > /sys/class/gpio/export

echo 1 > /sys/class/gpio/gpio251/value

Best Regards,

Matthew Starr

0 Kudos
Reply