c - BCM2708 (RPi) Rasbpian FIQ not triggered -
i have written linux loadable kernel module attempts attach fiq service gpio edge transistions. pin in question on gpio0 (irq 49) attempt configure fiq follows:
#ifndef gpio_base #define gpio_base 0x7e200000 #endif #define gpio_len 0x60 #define gpio_gpeds0 0x10 #define gpio_gpeds1 0x11 #define gpio_gpren0 0x13 #define gpio_gpren1 0x14 #define gpio_gpfen0 0x16 #define gpio_gpfen1 0x17 #define air_base 0x7e00b200 #define air_len 0x28 #define air_ip2 2 // irq pending source 63:32 #define air_fiq 3 // fiq config register #define air_fiq_an 0x80l // fiq enable field mask #define air_fiq_src 0x7fl // fiq source field mask #define air_en2 5 // irq enable irq source 63:32 #define air_de2 8 // irq disable irq source 63:32 #define air_gpio0_irq 49 struct { uint32_t wr_p; } fiq_data_s; extern unsigned char pulse_logger_fiq_handler, pulse_logger_fiq_handler_end; static struct fiq_handler pulse_logger_fh = { .name = "pulse_logger_fiq_handler" }; static int __init pulse_logger_init(void) { gpioreg = ioremap(gpio_base, gpio_len); aircreg = ioremap(air_base, air_len); fiq_data_s.wr_p = (uint32_t)&wr_p; // log offset store system counter printk(kern_info "enabling fiq...\n"); printk(kern_info "\tdisable gpio0 irq\n"); // disable irq tied fiq disable_irq_nosync(air_gpio0_irq); printk(kern_info "\tconfig gpio edge events\n"); writel(air_gpio0_msk, gpioreg + gpio_gpeds0); gpren0 = readl((const volatile void *)(gpioreg + gpio_gpren0)); gpren0 |= air_gpio0_msk; writel(gpren0, gpioreg + gpio_gpren0); gpfen0 = readl((const volatile void *)(gpioreg + gpio_gpfen0)); gpfen0 |= air_gpio0_msk; writel(gpfen0, gpioreg + gpio_gpfen0); printk(kern_info "\tclaim fiq\n"); // reserve fiq ret = claim_fiq(&pulse_logger_fh); if (ret){ printk(kern_info "failed claim fiq (%d)!\n", ret); goto fail1; } // copy fiq vector location printk(kern_info "\tcopying handler\n"); set_fiq_handler(&pulse_logger_fiq_handler, &pulse_logger_fiq_handler_end - &pulse_logger_fiq_handler); // store symbol pointers in fiq registers printk(kern_info "\tstoring registers\n"); memset(®s,0, sizeof(regs)); regs.arm_r8 = (long)&fiq_data_s; set_fiq_regs(®s); printk(kern_info "\tenable fiq\n"); // enable fiq enable_fiq(air_gpio0_irq); local_fiq_enable(); return 0; }
i find fiq register has invalid entry of 0x54 force fiq register:
writel(0x80 | air_gpio0_irq, (volatile void *)(aircreg + air_fiq));
i have written fiq follows:
#define data_ack_offset 12 entry(pulse_logger_fiq_handler) /* acknowledge interrupt */ /* write pin_ack event_status_offset register */ ldr r14, [r8, #data_ack_offset] /* load address */ mov r12, #pin_ack str r12, [r14, #0] ldr r14, [r8, #0] /* load address */ ldr r14, [r14, #0] /* load value */ add r14, r14, #1 ldr r12, [r8, #0] /* load address */ str r14, [r12, #0] /* return fiq */ subs pc, lr, #4 pulse_logger_fiq_handler_end:
i toggle line 20 times (using gpio) @ end of run wr_p == 1
.
if run code standard isr wr_p == 20
, leaving me believe isr code valid, need understand why fiq appears firing once.
static irqreturn_t pulse_isr(int irq, void *data) { uint32_t fiq_data_addr = (uint32_t)&fiq_data_s; *((uint32_t*)*((uint32_t*)fiq_data_addr)) += 1; __asm__ __volatile__ ( "mov r8, %[fiqbase] \n" "ldr r14, [r8, #12] \n\t" /* load address */ "mov r12, #0x00000010 \n\t" "str r12, [r14, #0] \n\t" "ldr r14, [r8, #0] \n\t"/* load address */ "ldr r14, [r14, #0] \n\t"/* load value */ "add r14, r14, #1 \n\t" "ldr r12, [r8, #0] \n\t" /* load address */ "str r14, [r12, #0] \n\t" :: [fiqbase] "r" (fiq_data_addr) : "r8", "r12", "r14"); return irq_handled; }
if dig in [local_]enable_fiq()
doesn't touches hardware @ why think have write register but, don't see happening in other drivers have looked @ online i'm confused.
is there reason why triggering once (even if don't write fiq register)?
i figured out, r13-r14 not general purpose registers. these sp , lr.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337h/chdedegj.html
a rewrite use r8-r12 has working.
Comments
Post a Comment