Beagleboard & QNX: GPIO Interrupts

This is a short guide on how to use the GPIO interrupts on the Beagleboard running QNX.

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:

  1. Beagleboard technical reference – http://beagleboard.org/resources
  2. OMAP3530 techinical reference manual (TRM) – http://focus.ti.com/docs/prod/folders/print/omap3515.html

steps overview:

  1. change mux to get GPIO signals (/src/hardware/startup/boards/omap3530/init_pinmux.c)
  2. add interrupt triggers (edge/level)
  3. write interrupt handler

For this guide, I will use use GPIO 130 and 131 as interrupt lines. Refer to BB TRM section 8.19.1 for what GPIO lines are available. Refer to section 7.4.4.3 in the TRM for which register the GPIO is muxed on. So in init_pinmux.c, I add:

/* ################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 33

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;
}

In my example you have to reset 2 status registers to have the interrupts trigger again. After count++, add:

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.

This entry was posted in omap 3530, qnx and tagged . Bookmark the permalink.

6 Responses to Beagleboard & QNX: GPIO Interrupts

  1. Alessandro says:

    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;

    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 <>Can you explain these lines?

    Thank you so much!

    Alessandro

    • davychiu says:

      –>> 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: 0×4800 2158).
      So, with the mask are you initializing the register setting all the 16 bits to zero? (and leaving the other 16 bits untouched?)

      Yes

      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?

      The pin is set to pull up to vdd. MUX is to set it to route to a GPIO pin instead of the second mmc controller.

      /* GPIO IRQ */
      out32(OMAP3530_GPIO5_BASE + OMAP2420_GPIO_RISINGDETECT, (1 << 2)|(1 << 3)); out32(OMAP3530_GPIO5_BASE + OMAP2420_GPIO_FALLINGDETECT, (1 << 2)|(1 <>Can you explain these lines?

      shift 1 left twice OR shift 1 left thrice = 00001100

      • Alessandro says:

        Hi,
        thanks for your reply.
        I was able to run your example, but I didn’t really understande the following code:

        out32(omap3530_intc_base + 0xa8, 0×2);
        out32(GPIO5 + OMAP35XX_GPIO_IRQSTATUS1, in32(GPIO5 + OMAP35XX_GPIO_IRQSTATUS1) | 0xFFFFFFFF);

        Can you explain me?

        Thanks

        • Alessandro says:

          Hi,
          expecially, I didn’t understand the instruction out32(omap3530_intc_base + 0xa8, 0×2): I saw on the TRM that the intc register offsets arrive up to 0x10 and not 0xa8. Maybe I missi something?

          Bye

          Alessandro

          • davychiu says:

            That instruction resets the trigger if I remember correctly. You should be able to follow the registers with the address. If not, they addresses may have changed in later revisions.

  2. Allen Chen says:

    Hi,

    I learn how to use GPIO on Beaglebone & QNX. Can you tell me whether Beaglebone & QNX can control a DC Servo Motor? If yes, what are the main steps to do it?

    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *