From: rketcham <Ric...@gm...> - 2008-03-25 14:23:24
|
Hello Everyone, Forgive me if this the wrong place to post this. I have a user space application (which may become a kernel space driver in the future) which will connect the SSP/SPI port to a pseudo terminal. What I want to do is I want the chip connected to the SPI port to trigger an interrupt on GPIO 22. What I need to know is how do I setup the interrupt (falling edge) and how do I connect my interrupt service routine such that it runs when the interrupt is triggered. Do I need to set up a vector table? If you could give me as much detail as you can and/or any example code, I would really appreciate it. BTW: I'm using DMA to access the registers. Thanks! Rich This is what I have so far (I still need to setup the direction register and alternate function register): /************************************************************************** * IRQ_Setup **************************************************************************/ void IRQ_Setup(int fd) { //Interrupt Priority Registers int ipr0 = getmem(IPR0);// Get the register values from the top priority register ipr0 |= (0x1 << 10); //Set the GPIO as top priority putmem(IPR0,ipr0);//Write to the register //Interrupt Control Mask Register int icmr = getmem(ICMR); //Read the register icmr |= (0x1 << 10);//Unmask GPIO_x putmem(ICMR,icmr); //Write to the register //Interrrupt Controller Level Registers int iclr = getmem(ICLR); //Read the register iclr &= ~(0x1 << 10);//Mask GPIO_x to create an IRQ putmem(ICLR,iclr); //Write to the register } -- View this message in context: http://www.nabble.com/PXA270-Interrupt-Help-tp16275103p16275103.html Sent from the Gumstix mailing list archive at Nabble.com. |
From: Dave H. <dhy...@gm...> - 2008-03-25 14:43:51
|
Hi Rich, > Forgive me if this the wrong place to post this. I have a user space > application (which may become a kernel space driver in the future) which > will connect the SSP/SPI port to a pseudo terminal. What I want to do is I > want the chip connected to the SPI port to trigger an interrupt on GPIO 22. > > What I need to know is how do I setup the interrupt (falling edge) and how > do I connect my interrupt service routine such that it runs when the > interrupt is triggered. Do I need to set up a vector table? If you could > give me as much detail as you can and/or any example code, I would really > appreciate it. So you can't really do interrupts from a user space application. This requires using a kernel module or linking code directly into the kernel. I've put together a kernel/module & user mode app that will do what you want. See over here: <http://docswiki.gumstix.com/GPIO_event> >From the kernel, registering an irq is done with the request_irq function. This also has flags for setting up the interrupt to occur on the rising or falling edges. You can see how it's done in the gpio-event-drv.c and searching for request_irq. The gpio_event_irq function is the interrupt dispatch function which will be called when an interrupt occurs for the particular gpio that it was registered against. -- Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ |
From: rketcham <Ric...@gm...> - 2008-04-07 16:41:43
|
Hey Dave, Thanks for the help. I've started writing a driver and I'm down to handling the interrupt piece. Is there any reason why the following wouldn't work in the interrupt handler? baseptr = ioremap(NSSPCR0, MapSize);//Create the map. This is the IRQ function: #define MapSize 4096 #define NSSPCR0 0x41700000 /************************************************************************** * spi_irqhandler * Handles the spi irq **************************************************************************/ irqreturn_t spi_irqhandler(int irq, void *dev_id, struct pt_regs *regs) { printk("INTERRUPTED!\n"); /********************************* * IRQ Handler Barfs for whatever reason * ... with this in it.... * ******************************/ baseptr = ioremap(NSSPCR0, MapSize);//Create the map. return IRQ_HANDLED; } This is the dump when the chip creates the interrupt: # INTERRUPTED! kernel BUG at mm/vmalloc.c:171! Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = c0004000 [00000000] *pgd=00000000 Internal error: Oops: 817 [#1] Modules linked in: spi_driver(P) cpufreq_conservative vfat fat nls_base sa1100_wdt ipv6 af_packet ohci_hcd usbcore pxa2xx_cs pxa2xx_core pcmcia pcmcia_core firmware_class smc91x mii gumstix_smc91x unix CPU: 0 PC is at __bug+0x20/0x2c LR is at 0xc01e81c8 pc : [<c002d878>] lr : [<c01e81c8>] Tainted: P sp : c01e1de8 ip : c01e81c8 fp : c01e1df4 r10: a00152f4 r9 : 69054117 r8 : e8000000 r7 : 00000001 r6 : 00000000 r5 : c8800000 r4 : 00001000 r3 : 00000000 r2 : 00000001 r1 : 00000001 r0 : 00000023 Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment kernel Control: 397F Table: A7684000 DAC: 00000017 Process swapper (pid: 0, stack limit = 0xc01e0260) Stack: (0xc01e1de8 to 0xc01e2000) 1de0: c01e1e1c c01e1df8 c00706b0 c002d864 00000077 00001000 1e00: 00041700 00000000 00000077 a0015328 c01e1e34 c01e1e20 c007085c c0070678 1e20: ffffffff 000000d0 c01e1e44 c01e1e38 c007088c c0070844 c01e1e94 c01e1e48 1e40: c0030350 c0070870 c01e1ec4 00000000 c00420b4 c0051654 0000f18c 00000077 1e60: 00000000 00000000 00000077 00000000 00000000 00000000 00000077 a0015328 1e80: 69054117 a00152f4 c01e1eac c01e1e98 c0030640 c003030c bf0ab938 00000077 1ea0: c01e1ec4 c01e1eb0 bf0ab954 c00305e8 c01e1ef4 c7c626e0 c01e1ee4 c01e1ec8 1ec0: c005a4c4 bf0ab928 c01e3dc0 00000077 c7c626e0 c02105c8 c01e1f04 c01e1ee8 1ee0: c005b7f4 c005a434 c01e1f14 00000001 c01e3dc0 00000078 c01e1f24 c01e1f08 1f00: c00334f8 c005b6f4 c01e1f24 0000000a c01e2280 00000000 c01e1f44 c01e1f28 1f20: c002a598 c0033424 c0045fe8 ffffffff c01e1f7c 00000400 c01e1f9c c01e1f48 1f40: c0029830 c002a560 00000001 c01e0000 a0000013 20000013 c002ad64 c01e0000 1f60: c00165a8 c02105c8 a0015328 69054117 a00152f4 c01e1f9c c01e1f90 c01e1f90 1f80: c002adac c002adb8 20000013 ffffffff c01e1fb4 c01e1fa0 c002ab3c c002ad70 1fa0: c0207394 c01f39b0 c01e1fc4 c01e1fb8 c0029138 c002ab10 c01e1ff4 c01e1fc8 1fc0: c0008aec c0029120 c00083e4 00000000 00000000 c00165a8 00000000 0000397d 1fe0: c01f3a64 c01e63a4 00000000 c01e1ff8 a0008030 c00088cc 00000000 00000000 Backtrace: [<c002d858>] (__bug+0x0/0x2c) from [<c00706b0>] (__get_vm_area_node+0x44/0x18c) [<c007066c>] (__get_vm_area_node+0x0/0x18c) from [<c007085c>] (__get_vm_area+0x24/0x2c) r8 = A0015328 r7 = 00000077 r6 = 00000000 r5 = 00041700 r4 = 00001000 [<c0070838>] (__get_vm_area+0x0/0x2c) from [<c007088c>] (get_vm_area+0x28/0x30) [<c0070864>] (get_vm_area+0x0/0x30) from [<c0030350>] (__ioremap_pfn+0x50/0x2dc) [<c0030300>] (__ioremap_pfn+0x0/0x2dc) from [<c0030640>] (__ioremap+0x64/0x70) [<c00305dc>] (__ioremap+0x0/0x70) from [<bf0ab954>] (spi_irqhandler+0x38/0x50 [spi_driver]) r4 = 00000077 [<bf0ab91c>] (spi_irqhandler+0x0/0x50 [spi_driver]) from [<c005a4c4>] (handle_IRQ_event+0x9c/0xe4) r4 = C7C626E0 [<c005a428>] (handle_IRQ_event+0x0/0xe4) from [<c005b7f4>] (handle_edge_irq+0x10c/0x150) r7 = C02105C8 r6 = C7C626E0 r5 = 00000077 r4 = C01E3DC0 [<c005b6e8>] (handle_edge_irq+0x0/0x150) from [<c00334f8>] (pxa_gpio_demux_handler+0xe0/0x158) r6 = 00000078 r5 = C01E3DC0 r4 = 00000001 [<c0033418>] (pxa_gpio_demux_handler+0x0/0x158) from [<c002a598>] (asm_do_IRQ+0x44/0x60) r6 = 00000000 r5 = C01E2280 r4 = 0000000A [<c002a554>] (asm_do_IRQ+0x0/0x60) from [<c0029830>] (__irq_svc+0x30/0x80) r6 = 00000400 r5 = C01E1F7C r4 = FFFFFFFF [<c002ad64>] (default_idle+0x0/0x5c) from [<c002ab3c>] (cpu_idle+0x38/0x54) [<c002ab04>] (cpu_idle+0x0/0x54) from [<c0029138>] (rest_init+0x24/0x2c) r5 = C01F39B0 r4 = C0207394 [<c0029114>] (rest_init+0x0/0x2c) from [<c0008aec>] (start_kernel+0x22c/0x284) [<c00088c0>] (start_kernel+0x0/0x284) from [<a0008030>] (0xa0008030) Code: e1a01000 e59f000c eb00311a e3a03000 (e5833000) Kernel panic - not syncing: Aiee, killing interrupt handler! Thanks! Rich -- View this message in context: http://www.nabble.com/PXA270-Interrupt-Help-tp16275103p16537545.html Sent from the Gumstix mailing list archive at Nabble.com. |
From: Dave H. <dhy...@gm...> - 2008-04-07 17:16:44
|
Hi Rich, On Mon, Apr 7, 2008 at 9:41 AM, rketcham <Ric...@gm...> wrote: > > Hey Dave, > Thanks for the help. I've started writing a driver and I'm down to handling > the interrupt piece. Is there any reason why the following wouldn't work in > the interrupt handler? > > baseptr = ioremap(NSSPCR0, MapSize);//Create the map. You're not allowed to call any type of blocking function from within an interrupt handler. ioremap is a potentially blocking function, so it cannot be called from an interrupt handler. Normally, you would do all of the memory mapping, memory allocation stuff outside of the interrupt handler and the interrupt handler would just copy stuff around. Why do you think you need it from within the interrupt handler? Perhaps you could describe what you're trying to do, and I can suggest a "traditional" method of dealing with that situation. -- Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ |
From: rketcham <Ric...@gm...> - 2008-04-08 13:43:56
|
Dave, Ahhh. That's good to know. I'm actually working on a driver to communicate with my SPI to UART chip. I wanted the SPI chip to raise an interrupt when it's RX buffer reached a certain level. On the interrupt, I want the interrupt service routine to check several registers on the SPI chip to determine the cause of the interrupt and retrieve data from the buffer. To do this, I think I only need access to three registers on the PXA270: SSDR2 for TX and RX (0x41700010) GPCR2 for GPIO clear (0x40E0002C) GPSR2 for GPIO set(0x40E00020) The last two are for my chip select (although, I could use the Frame pin). What's the usual way for doing this? Thanks for your help. Rich Dave Hylands wrote: > > Why do you think you need it from within the interrupt handler? > Perhaps you could describe what you're trying to do, and I can suggest > a "traditional" method of dealing with that situation. > -- View this message in context: http://www.nabble.com/PXA270-Interrupt-Help-tp16275103p16558444.html Sent from the Gumstix mailing list archive at Nabble.com. |
From: Ned F. <nfo...@wh...> - 2008-04-08 14:48:01
|
rketcham wrote: > Dave, > Ahhh. That's good to know. I'm actually working on a driver to communicate > with my SPI to UART chip. I wanted the SPI chip to raise an interrupt when > it's RX buffer reached a certain level. On the interrupt, I want the > interrupt service routine to check several registers on the SPI chip to > determine the cause of the interrupt and retrieve data from the buffer. > > To do this, I think I only need access to three registers on the PXA270: > > SSDR2 for TX and RX (0x41700010) > GPCR2 for GPIO clear (0x40E0002C) > GPSR2 for GPIO set(0x40E00020) > > The last two are for my chip select (although, I could use the Frame pin). > What's the usual way for doing this? If you are new to kernel programming and are trying to write a device driver, as was my situation last year, I recommend that an easier to way to learn would be to read a good reference book. I found the following to be very helpful: "Linux Device Drivers" THIRD EDITION, by Jonathan Corbet, Alessandro, Rubini, and Greg Kroah-Hartman, published by O'Reilly. The third edition covers the 2.6 kernel. Even though I was expanding a driver that already existed and worked (pxa2xx_spi.c), I could never have understood all the things I needed to know by polling a mailing list. -- Ned Forrester nfo...@wh... Oceanographic Systems Lab 508-289-2226 Applied Ocean Physics and Engineering Dept. Woods Hole Oceanographic Institution Woods Hole, MA 02543, USA http://www.whoi.edu/sbl/liteSite.do?litesiteid=7212 http://www.whoi.edu/hpb/Site.do?id=1532 http://www.whoi.edu/page.do?pid=10079 |
From: Dave H. <dhy...@gm...> - 2008-04-08 14:09:10
|
Hi Rich, > Ahhh. That's good to know. I'm actually working on a driver to communicate > with my SPI to UART chip. I wanted the SPI chip to raise an interrupt when > it's RX buffer reached a certain level. On the interrupt, I want the > interrupt service routine to check several registers on the SPI chip to > determine the cause of the interrupt and retrieve data from the buffer. > > To do this, I think I only need access to three registers on the PXA270: > > SSDR2 for TX and RX (0x41700010) > GPCR2 for GPIO clear (0x40E0002C) > GPSR2 for GPIO set(0x40E00020) > > The last two are for my chip select (although, I could use the Frame pin). > What's the usual way for doing this? In kernel space, you can just access them directly. No need for ioremap are anything fancy. However, it's important to understand that the registers in the data sheet are presented using physical addresses, while the kernel is running in a virtual space. If you take a look in include/asm-arm/arch-pxa/pxa-regs.h you'll see that most of the register definitions are done using the __REG macro. I normally check the pxa-regs.h file first, since that's where most of the register definitions occur. #include <asm/arch/hardware.h> #include <asm/arch/pxa-regs.h> You'll find that SSDR_P2, GPCR2 and GPSR2 are already defined. For setting up direction and value of gpio pins, I recommend: #include <asm/gpio.h> gpio_direction_input( pin ); gpio_direction_output( pin, initial_value ); gpio_set_value( pin, value ); gpio_get_value( pin ); -- Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ |
From: rketcham <Ric...@gm...> - 2008-04-08 21:17:45
|
Hi Dave, If I wanted to write to SSDR_P2 would I just assign it the value? Like this: SSDR_P2 = 0xffff; -Rich Dave Hylands wrote: > > Hi Rich, > >> Ahhh. That's good to know. I'm actually working on a driver to >> communicate >> with my SPI to UART chip. I wanted the SPI chip to raise an interrupt >> when >> it's RX buffer reached a certain level. On the interrupt, I want the >> interrupt service routine to check several registers on the SPI chip to >> determine the cause of the interrupt and retrieve data from the buffer. >> >> To do this, I think I only need access to three registers on the PXA270: >> >> SSDR2 for TX and RX (0x41700010) >> GPCR2 for GPIO clear (0x40E0002C) >> GPSR2 for GPIO set(0x40E00020) >> >> The last two are for my chip select (although, I could use the Frame >> pin). >> What's the usual way for doing this? > > In kernel space, you can just access them directly. No need for > ioremap are anything fancy. > > However, it's important to understand that the registers in the data > sheet are presented using physical addresses, while the kernel is > running in a virtual space. If you take a look in > include/asm-arm/arch-pxa/pxa-regs.h you'll see that most of the > register definitions are done using the __REG macro. > > I normally check the pxa-regs.h file first, since that's where most of > the register definitions occur. > > #include <asm/arch/hardware.h> > #include <asm/arch/pxa-regs.h> > > You'll find that SSDR_P2, GPCR2 and GPSR2 are already defined. > > For setting up direction and value of gpio pins, I recommend: > > #include <asm/gpio.h> > > gpio_direction_input( pin ); > gpio_direction_output( pin, initial_value ); > gpio_set_value( pin, value ); > gpio_get_value( pin ); > > -- > Dave Hylands > Vancouver, BC, Canada > http://www.DaveHylands.com/ > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Register now and save $200. Hurry, offer ends at 11:59 p.m., > Monday, April 7! Use priority code J8TLD2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > gumstix-users mailing list > gum...@li... > https://lists.sourceforge.net/lists/listinfo/gumstix-users > > -- View this message in context: http://www.nabble.com/PXA270-Interrupt-Help-tp16275103p16573756.html Sent from the Gumstix mailing list archive at Nabble.com. |
From: Dave H. <dhy...@gm...> - 2008-04-08 21:53:33
|
Hi Rich, > If I wanted to write to SSDR_P2 would I just assign it the value? Like this: > > SSDR_P2 = 0xffff; Yep - and reading is just like: val = SSDR_P2; You need to carefully read the datasheet for each register. Some registers are read-only, some are write-only. Some have non-obvious behaviors, like writing a 1 clears a bit. You also need to be wary of read-modify-write operations, especially outside of the ISR handler. -- Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ |
From: Bob E. <sna...@gm...> - 2008-04-10 19:39:17
|
What are the basic steps to starting to make your own module with OE? On Tue, Apr 8, 2008 at 4:53 PM, Dave Hylands <dhy...@gm...> wrote: > Hi Rich, > > > If I wanted to write to SSDR_P2 would I just assign it the value? Like > this: > > > > SSDR_P2 = 0xffff; > > Yep - and reading is just like: > > val = SSDR_P2; > > You need to carefully read the datasheet for each register. Some > registers are read-only, some are write-only. Some have non-obvious > behaviors, like writing a 1 clears a bit. > > You also need to be wary of read-modify-write operations, especially > outside of the ISR handler. > > -- > Dave Hylands > Vancouver, BC, Canada > http://www.DaveHylands.com/ > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Register now and save $200. Hurry, offer ends at 11:59 p.m., > Monday, April 7! Use priority code J8TLD2. > > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > gumstix-users mailing list > gum...@li... > https://lists.sourceforge.net/lists/listinfo/gumstix-users > |
From: Michael <mh...@de...> - 2008-04-10 21:42:13
|
On Thu, Apr 10, 2008 at 02:39:16PM -0500, Bob Evans wrote: > What are the basic steps to starting to make your own module with OE? > ... Most important would be to learn about GNU/linux kernel (2.6.x) pro- gramming. In the kernel source tree are examples / templates you can look at. Then write and compile an empty module and check how it fits into your arm-kernel and if the module tools work with it. then fill this empty module with your code. Greetings, Michael |