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
Solved! Go to Solution.
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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)
return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(100, 200);
+ udelay(200);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)
return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(100, 200);
+ udelay(200);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)
return -ETIMEDOUT;
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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)
return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(100, 200);
+ udelay(200);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)
return -ETIMEDOUT;
@@ -359,7 +359,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK))
return -ETIMEDOUT;
@@ -378,7 +378,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(100, 200);
+ udelay(200);
if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
return -ETIMEDOUT;
@@ -397,7 +397,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
flexcan_write(reg, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->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, ®s->mcr);
while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST))
- usleep_range(10, 20);
+ udelay(20);
if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)
return -ETIMEDOUT;
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
Hi Fabio,
Were you able to reproduce the problem? I was not.
Regards,
Alejandro
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
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:
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.
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
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