My setup:
Beagleboard C3
512MB SD boot
4-port USB 2.0 hub
linksys USB 1.1 100TX adapter (for debug through momentics IDE)
references required:
- Beagleboard technical reference - http://beagleboard.org/resources
- OMAP3530 techinical reference manual (TRM) - http://focus.ti.com/docs/prod/folders/print/omap3515.html
- change mux to get GPIO signals (/src/hardware/startup/boards/omap3530/init_pinmux.c)
- add interrupt triggers (edge/level)
- write interrupt handler
/* ################GPIO5 SETUP################### */
/* MMC2 CLK */
pad = in32(CONTROL_PADCONF_MMC2_CLK) & 0x0000ffff;
out32(CONTROL_PADCONF_MMC2_CLK, pad | INPUTENABLE1 | PULLTYPE1_UP | PULLUDENABLE1 | MUXMODE1_MODE4);
/* MMC2 CMD */
pad = in32(CONTROL_PADCONF_MMC2_CLK) & 0xffff0000;
out32(CONTROL_PADCONF_MMC2_CLK, pad | INPUTENABLE0 | PULLTYPE0_UP | PULLUDENABLE0 | MUXMODE0_MODE4);
/* GPIO IRQ */
out32(OMAP3530_GPIO5_BASE + OMAP2420_GPIO_RISINGDETECT, (1 << 2)|(1 << 3));
out32(OMAP3530_GPIO5_BASE + OMAP2420_GPIO_FALLINGDETECT, (1 << 2)|(1 << 3));
Create a new QNX project to test the interrupt handler. GPIO5 lines share IRQ 33, so I would need to check the irqstatus of each line if I use more than one interrupt.
#define GPIO5_IRQ 33In my example you have to reset 2 status registers to have the interrupts trigger again. After count++, add:
int count;
int error;
struct sigevent event;
const struct sigevent *
isr_handler (void *arg, int id)
{
return (&event);
}
void *
int_thread (void *arg)
{
// enable I/O privilege
ThreadCtl (_NTO_TCTL_IO, 0);
// attach the ISR to IRQ
if (InterruptAttach (GPIO5_IRQ, isr_handler, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK) == -1) {
error = 1;
}
while (1)
{
InterruptWait (NULL, NULL);
count++;
}
}
int main(int argc, char *argv[]) {
event.sigev_notify = SIGEV_INTR;
printf("Creating interrupt thread...\n");
pthread_create (NULL, NULL, int_thread, NULL);
delay(5);
while(!error) {
printf("count=%i\n", count);
fflush(stdout);
sleep(1);
}
return EXIT_SUCCESS;
}
out32(omap3530_intc_base + 0xa8, 0x2);
out32(GPIO5 + OMAP35XX_GPIO_IRQSTATUS1, in32(GPIO5 + OMAP35XX_GPIO_IRQSTATUS1) | 0xFFFFFFFF);
I will make a more complete guide later on... feel free to comment or email questions.
2 comments:
Hi,
I would like to start using the GPIO Interrupts with QNX on BeagleBoard and I found your guide very interesting.
However, I didn't understand so good what I should set-up the GPIO5.
Practically,
/* ################GPIO5 SETUP################### */
/* MMC2 CLK */
pad = in32(CONTROL_PADCONF_MMC2_CLK) & 0x0000ffff;
-->> Why do you do the & between CONTROL_PADCONF_MMC2_CLK and 0x0000ffff?
I've read that mmc2_clk is Mode 0 on CONTROL_PADCONF_MMC2_CLK[15:0] (Address: 0x4800 2158).
So, with the mask are you initializing the register setting all the 16 bits to zero? (and leaving the other 16 bits untouched?)
out32(CONTROL_PADCONF_MMC2_CLK, pad | INPUTENABLE1 | PULLTYPE1_UP | PULLUDENABLE1 | MUXMODE1_MODE4);
-->> Why you use INPUTENABLE1 | PULLTYPE1_UP | PULLUDENABLE1 | MUXMODE1_MODE4 ? Can you explain that?
/* MMC2 CMD */
pad = in32(CONTROL_PADCONF_MMC2_CLK) & 0xffff0000;
-->> Why do you do the & between CONTROL_PADCONF_MMC2_CLK and 0xffff0000 and not 0x0000ffff?
out32(CONTROL_PADCONF_MMC2_CLK, pad | INPUTENABLE0 | PULLTYPE0_UP | PULLUDENABLE0 | MUXMODE0_MODE4);
/* GPIO IRQ */
out32(OMAP3530_GPIO5_BASE + OMAP2420_GPIO_RISINGDETECT, (1 << 2)|(1 << 3));
out32(OMAP3530_GPIO5_BASE + OMAP2420_GPIO_FALLINGDETECT, (1 << 2)|(1 << 3));
-->>Can you explain these lines?
Thank you so much!
Alessandro
Post a Comment