Начал разбираться с таймерами. Есть устройство с линуксом на борту с SPI-клавиатурой. Я хочу по срабатыванию таймера прибивать авторепит у клавиатуры. Вот функция, регистрирующая нажатие:
static void key_press(void)
{
if (last_scan_code != 0)
{
uint8_t i = 0;
for (; i < NUMBER_OF_KEYS; i++)
{
if (KEYS[i].scan_code == last_scan_code)
{
init_timer(&my_timer);
my_timer.expires = jiffies + delay;
my_timer.data = 0;
my_timer.function = my_timer_function;
add_timer(&my_timer);
if (KEYS[i].key == 79) /** по нажатию на кнопку "1" прибиваем авторепит */
{
del_timer(&kbd_dev->timer);
}
else
{
input_report_key(kbd_dev, KEYS[i].key, 1);
input_sync(kbd_dev);
snd_squeak(3000, 120000, 240000);
STATUS.last_key = KEYS[i].key;
}
}
}
}
}
А это обработчик таймера:
void my_timer_function(unsigned long data)
{
printk(KERN_INFO "\nHello from my_timer_function!\n");
del_timer(&my_timer);
del_timer(&(kbd_dev->timer));
}
Компилирую модуль, подгружаю его, тыкаю в кнопки. Дальше происходит странное - примерно на каждое 15-20 нажатие вываливается простыня:
14:38:29.800; Pressed 0x39 key {9} {NM:0} {NSC:0} {NVK:0} {MOD:20000000} {REPIT:true} [text:9]
Hello from my_timer_function!
Unable to handle kernel NULL pointer dereference at virtual address 00000004
pgd = c0004000
[00000004] *pgd=00000000
Internal error: Oops: 817 [#1] PREEMPT
Modules linked in: power adc thermal busmanager dsp kbd squeak
CPU: 0 Not tainted (2.6.27.8 #6)
PC is at run_timer_softirq+0x154/0x248
LR is at run_timer_softirq+0x1c/0x248
pc : [<c00482f0>] lr : [<c00481b8>] psr: 80000093
sp : c0325eb4 ip : c0325ebc fp : c0325eec
r10: c0344208 r9 : c0344008 r8 : c0344408
r7 : bf002694 r6 : c0324000 r5 : 00000000 r4 : c0343600
r3 : 00000000 r2 : c0325ebc r1 : bf004078 r0 : c03436b8
Flags: Nzcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel
Control: 0005317f Table: 83a3c000 DAC: 00000017
Process swapper (pid: 0, stack limit = 0xc0324260)
Stack: (0xc0325eb4 to 0xc0326000)
5ea0: c0325ebc c0343e08 00000000
5ec0: c3977970 c0343478 00000001 0000000a c0343440 00000001 c0345b70 00000000
5ee0: c0325f18 c0325ef0 c0043390 c00481ac c032c724 00000010 00000000 00000002
5f00: 00000001 c0324000 8001b99c c0325f28 c0325f1c c0043440 c004333c c0325f44
5f20: c0325f2c c0020048 c0043408 ffffffff f4008000 00010000 c0325f9c c0325f48
5f40: c00208b8 c0020010 00000000 0005317f 0005217f 60000013 c0021e10 c0324000
5f60: c0021e10 c033e028 8001b9d0 41069264 8001b99c c0325f9c 600000d3 c0325f90
5f80: c0021e54 c0021e60 60000013 ffffffff c0325fbc c0325fa0 c0021ddc c0021e20
5fa0: c0324000 c033dff0 c001cda8 c0327ce8 c0325fd0 c0325fc0 c027f07c c0021db0
5fc0: c0345ee8 c0325ff4 c0325fd4 c0008960 c027f01c c0008480 c001cda8 00053175
5fe0: c033e08c c001d1ac 00000000 c0325ff8 80008034 c0008720 00000000 00000000
Backtrace:
[<c004819c>] (run_timer_softirq+0x0/0x248) from [<c0043390>] (__do_softirq+0x64/0xcc)
[<c004332c>] (__do_softirq+0x0/0xcc) from [<c0043440>] (irq_exit+0x48/0x64)
[<c00433f8>] (irq_exit+0x0/0x64) from [<c0020048>] (__exception_text_start+0x48/0x60)
[<c0020000>] (__exception_text_start+0x0/0x60) from [<c00208b8>] (__irq_svc+0x38/0xc4)
Exception stack(0xc0325f48 to 0xc0325f90)
5f40: 00000000 0005317f 0005217f 60000013 c0021e10 c0324000
5f60: c0021e10 c033e028 8001b9d0 41069264 8001b99c c0325f9c 600000d3 c0325f90
5f80: c0021e54 c0021e60 60000013 ffffffff
r6:00010000 r5:f4008000 r4:ffffffff
[<c0021e10>] (default_idle+0x0/0x58) from [<c0021ddc>] (cpu_idle+0x3c/0x70)
[<c0021da0>] (cpu_idle+0x0/0x70) from [<c027f07c>] (rest_init+0x70/0x84)
r7:c0327ce8 r6:c001cda8 r5:c033dff0 r4:c0324000
[<c027f00c>] (rest_init+0x0/0x84) from [<c0008960>] (start_kernel+0x250/0x2a8)
r4:c0345ee8
[<c0008710>] (start_kernel+0x0/0x2a8) from [<80008034>] (0x80008034)
r6:c001d1ac r5:c033e08c r4:00053175
Code: e5913000 e591700c e5915010 e5823000 (e5832004)
Kernel panic - not syncing: Fatal exception in interrupt
ЧЯДНТ?