Hi everyone. I'm a beginner at embedded system & linux kernel, using i.MX6Q SabreSD kit for studying. When learing how to use Timer, I have a problem with I2C write operation.
- I have an I2C device driver, I setup a timer in probe() function to call my callback function (called "my_timer_callback") after 1 second:
setup_timer(&my_timer, my_timer_callback, 0);
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
- Inside my callback function, I send 1 byte to reset my I2C slave device & restart my Timer:
static void my_timer_callback(unsigned long data)
{
printk(KERN_INFO "----> %s\n", __func__);
i2c_smbus_write_byte_data(my_i2c_client, 0x00, 0x00);
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));
}
- When I boot up the kit with new kernel image, the booting is error & log in minicom looks like this:
...
----> my_timer_callback
clk_enable cannot be called in an interrupt context
[<c00509e4>] (unwind_backtrace+0x0/0x138) from [<c006b408>] (clk_enable+0x88/0x)
[<c006b408>] (clk_enable+0x88/0xa0) from [<c03c3fa8>] (i2c_imx_xfer+0x6c/0x75c)
[<c03c3fa8>] (i2c_imx_xfer+0x6c/0x75c) from [<c03c19cc>] (i2c_transfer+0xc8/0x1)
[<c03c19cc>] (i2c_transfer+0xc8/0x148) from [<c03c1d80>] (i2c_smbus_xfer+0x298/)
[<c03c1d80>] (i2c_smbus_xfer+0x298/0x564) from [<c03c22fc>] (i2c_smbus_write_by)
[<c03c22fc>] (i2c_smbus_write_byte_data+0x40/0x48) from [<c040335c>] (my_timer_)
[<c040335c>] (my_timer_callback+0x68/0xa4) from [<c009812c>] (run_timer_softirq)
[<c009812c>] (run_timer_softirq+0x134/0x3e4) from [<c0090478>] (__do_softirq+0x)
[<c0090478>] (__do_softirq+0xc8/0x25c) from [<c0090ac0>] (irq_exit+0x98/0xa0)
[<c0090ac0>] (irq_exit+0x98/0xa0) from [<c00431b4>] (do_local_timer+0x70/0x90)
[<c00431b4>] (do_local_timer+0x70/0x90) from [<c004934c>] (__irq_svc+0x4c/0xe8)
Exception stack(0xe6037e28 to 0xe6037e70)
7e20: e72f9c18 20000113 000025ed 00000000 e72f9800 e72f99d4
7e40: e72f9b40 e72f9c18 20000113 00000000 00000000 00000000 00000004 e6037e70
7e60: c043152c c06403e0 40000113 ffffffff
[<c004934c>] (__irq_svc+0x4c/0xe8) from [<c06403e0>] (_raw_spin_unlock_irqresto)
[<c06403e0>] (_raw_spin_unlock_irqrestore+0x18/0x40) from [<c043152c>] (sdhci_s)
[<c043152c>] (sdhci_set_ios+0x284/0x5ec) from [<c0420130>] (mmc_set_bus_mode+0x)
[<c0420130>] (mmc_set_bus_mode+0x3c/0x9c) from [<c0426dfc>] (mmc_sdio_init_card)
[<c0426dfc>] (mmc_sdio_init_card+0x438/0x570) from [<c0427398>] (mmc_attach_sdi)
[<c0427398>] (mmc_attach_sdio+0x94/0x368) from [<c0420ee8>] (mmc_rescan+0x24c/0)
[<c0420ee8>] (mmc_rescan+0x24c/0x2ac) from [<c00a3f5c>] (process_one_work+0x12c)
[<c00a3f5c>] (process_one_work+0x12c/0x494) from [<c00a4434>] (worker_thread+0x)
[<c00a4434>] (worker_thread+0x170/0x3cc) from [<c00a8528>] (kthread+0x80/0x88)
[<c00a8528>] (kthread+0x80/0x88) from [<c004a408>] (kernel_thread_exit+0x0/0x8)
kernel BUG at arch/arm/plat-mxc/clock.c:101!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1] PREEMPT SMP
Modules linked in:
CPU: 0 Tainted: G W (3.0.35-g582b0a0-dirty #229)
PC is at __bug+0x1c/0x28
LR is at __bug+0x18/0x28
pc : [<c004cfec>] lr : [<c004cfe8>] psr: 20000113
sp : e6037c28 ip : 00000000 fp : 00000001
r10: 00000001 r9 : ffff8c93 r8 : e6037ca8
r7 : c08dffe8 r6 : 00000001 r5 : e6037ca8 r4 : c08896f0
r3 : 00000000 r2 : c089741c r1 : 60000193 r0 : 00000033
Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 10c53c7d Table: 1000404a DAC: 00000015
PC: 0xc004cf6c:
cf6c e1a04000 e24dd010 e590003c eb01c3bb e3500000 0594003c 0a00000d e2841034
cf8c e594002c e891000e e88d000f ea000003 e59d000c eb01c3b1 e3500000 0a000006
cfac e1a0000d eb000d34 e3500000 aafffff7 e3a00000 e28dd010 e8bd8010 e59d000c
cfcc eafffffb e92d4008 e1a03000 e1a02001 e59f0010 e1a01003 eb17b2ab e3a03000
cfec e5833000 eafffffe c076de8c e30d0ea8 e30012e1 e92d4008 e34c0076 ebfffff0
d00c e1a01000 e30d0ec0 e92d4008 e34c0076 eb17b29d e30d0ea8 e30012c5 e34c0076
d02c ebffffe7 e92d4008 e1a02000 e1a03001 e30d0ee0 e1a0100e e34c0076 eb17b292
d04c e30d0ea8 e3001299 e34c0076 ebffffdc e92d4ff0 e24dd06c e1a06002 e1a08000
LR: 0xc004cf68:
cf68 e92d4010 e1a04000 e24dd010 e590003c eb01c3bb e3500000 0594003c 0a00000d
cf88 e2841034 e594002c e891000e e88d000f ea000003 e59d000c eb01c3b1 e3500000
cfa8 0a000006 e1a0000d eb000d34 e3500000 aafffff7 e3a00000 e28dd010 e8bd8010
cfc8 e59d000c eafffffb e92d4008 e1a03000 e1a02001 e59f0010 e1a01003 eb17b2ab
cfe8 e3a03000 e5833000 eafffffe c076de8c e30d0ea8 e30012e1 e92d4008 e34c0076
d008 ebfffff0 e1a01000 e30d0ec0 e92d4008 e34c0076 eb17b29d e30d0ea8 e30012c5
d028 e34c0076 ebffffe7 e92d4008 e1a02000 e1a03001 e30d0ee0 e1a0100e e34c0076
d048 eb17b292 e30d0ea8 e3001299 e34c0076 ebffffdc e92d4ff0 e24dd06c e1a06002
...
Please, help me to solve this problem. Thanks.
The hint is the very first message of your log "clk_enable cannot be called in an interrupt context".
So you need to move the clk_enable() to some other place which is not in interrupt context.
Regards,
Fabio Estevam
Hi Fabio,
I think I've found the reason for this problem. I'll find another solutions supported by Linux kernel.
Thanks for your reply.