Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - Interrupt management on Beaglebone running QNX 6.5: (10 Items)
   
Interrupt management on Beaglebone running QNX 6.5  
Hi guys,
I'm tryingot fogire out how can I use interrupts on my Beaglebone running QNX 6.5.
My need is to use GPIO1_12 as interrupt line when a user push down a botton.
In order to do so I've setup the GPIO1_12 in pullup mode in order to detect, thorough falling detect condiction when the
 user press the button.

Based on my researches, I've written the following code, it compiles but it doesn't work:
Do you have some suggetions?

Thanks guys.



################################ CODE #########################################

#include <cstdlib>
#include <iostream>
#include <sys/mman.h>
#include <pthread.h>
#include <sys/neutrino.h>
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <hw/inout.h>
#include <am335x.h>
#include <stdio.h>

#define AM335X_CTRL_BASE	        0x44E10000
#define conf_gpmc_ad12		0x0830 // (AM335X_CTRL_BASE+0x0830)
#define SLEWCTRL			        (0x1 << 6)
#define	RXACTIVE			(0x1 << 5)
#define	PULLUP_EN			(0x1 << 4) /* Pull UP Selection */
#define PULLUDEN			(0x0 << 3) /* Pull up enabled */
#define PULLUDDIS			(0x1 << 3) /* Pull up disabled */
#define MODE(val)			val
#define GPIO_OE 			0x134
#define AM335X_GPIO_SIZE	0x00001000
#define AM335X_GPIO1_BASE   0x4804C000
#define GPIO1_IRQ 99

int init_gpio1_12(void);
const struct sigevent * isr_handler (void *arg, int id);
void * int_thread (void *arg);

struct sigevent event;
uintptr_t ptr;
uintptr_t ptr2;
int count;
int error;

int main(int argc, char *argv[]) {

	init_gpio1_12();

	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;

}

int init_gpio1_12()
{
	int pad;

   	ThreadCtl(_NTO_TCTL_IO, 0);

        // The register that I want to use as gpio (conf_gpmc_ad12) is located at the address 0x0830, so I will map the 
memory from AM335X_CTRL_BASE addresss to AM335X_CTRL_BASE+0x0840
   	ptr = (uintptr_t)mmap_device_memory(0, AM335X_CTRL_BASE+0x0840, PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, 
AM335X_CTRL_BASE);

	if ( ptr == MAP_DEVICE_FAILED ) {
		perror( "mmap_device_memory for physical address failed");
		return -1;
	}

	pad = in32(ptr + conf_gpmc_ad12) & 0x0000ffff;

        // I set conf_gpmc_ad12 in MODE 7 to enable the pin as GPIO1_12
	out32(ptr + conf_gpmc_ad12, MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE | SLEWCTRL);

	//pad = in32(ptr + conf_gpmc_ad12);

   	ptr2 = (uintptr_t) mmap_device_memory(0, AM335X_GPIO_SIZE, PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, AM335X_GPIO1_BASE);


	if ( ptr2 == MAP_DEVICE_FAILED ) {
		perror( "mmap_device_memory for physical address failed");
		return -1;
	}

	out32(ptr2 + GPIO_OE,(1 << 12));

	out32(ptr2 + GPIO_FALLINGDETECT, (1 << 12));
}

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 (GPIO1_IRQ, isr_handler, NULL, 0, _NTO_INTR_FLAGS_TRK_MSK) == -1)
	{
		error = 1;
	}

	while (1)
	{
		InterruptWait (NULL, NULL);
		count++;
	}
}
Re: Interrupt management on Beaglebone running QNX 6.5  
Hi!

What does it mean:

out32(ptr2 + GPIO_OE,(1 << 12));

???
Re: Interrupt management on Beaglebone running QNX 6.5  
> Hi!
> 
> What does it mean:
> 
> out32(ptr2 + GPIO_OE,(1 << 12));
> 
> ???

out32 is a function that takes two inputs:

out32(addr,value)

The parameters are
1) address where to write
2) value to write

So :

ptr2 + GPIO_OE is the address.
(1 << 12) is the value: 1 << 12 means: shift value 1 of 12 position to left

More infomation can be found on the processor TRM.
Re: Interrupt management on Beaglebone running QNX 6.5  
Thanks, but i know what does this function do. But as are u sure that GPIO_OE (0x134) is correct value. If yes, what 
does it refer to?
Re: Interrupt management on Beaglebone running QNX 6.5  
And if u have solved this problem, can u say how? because im also trying to configure interrupt from PIN filling edge, 
but handler doesnt calls anymore.
Re: Interrupt management on Beaglebone running QNX 6.5  
Hi, I found that value in the TRM document for AM335X.
You can find it at http://www.ti.com/lit/ug/spruh73i/spruh73i.pdf
Page 4656

Actually I put this project in stand-by. If you have any update please, let me know.
Re: Interrupt management on Beaglebone running QNX 6.5  
Hi! I have solve my problem and now i'm getting interrupts. But i don't know what i exactly have edited in my code. So, 
i can simply send u my working source!
Re: Interrupt management on Beaglebone running QNX 6.5  
Yes, Thanks!
My email is alessandro [dot] nuke [@] gmail [dot] com
Re: Interrupt management on Beaglebone running QNX 6.5  
My email is: alessandro.nuke@gmail.com.

Thanks for sharing your code!

Alessandro


Re: Interrupt management on Beaglebone running QNX 6.5  
It is working code:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

#include <sys/neutrino.h>
#include <unistd.h>
#include <sys/mman.h>
#include <arm/mx6x.h>
#include <arm/mx6x_iomux.h>
#include <arm/inout.h>
#include <errno.h>

#define GPIO_PAD_OUTPUT ( PAD_CTL_PUS_100K_PU | PAD_CTL_ODE_DISABLE | PAD_CTL_SPEED_LOW | PAD_CTL_DSE_240_OHM  | 
PAD_CTL_SRE_SLOW )

#define GPIO_PAD_INPUT ( PAD_CTL_PKE_ENABLE | PAD_CTL_PUE_PULL | PAD_CTL_PUS_22K_PU | PAD_CTL_SPEED_LOW | \
                            PAD_CTL_DSE_80_OHM | PAD_CTL_HYS_ENABLE)

#define IRQ_GPIO7_13	365

#define MY_PIN			13

static uint32_t count = 0;
static uint32_t count_last;

static const struct sigevent *spi_intr(void *area, int id);

int main(int argc, char *argv[])
{
	printf("0\n");

	if (ThreadCtl(_NTO_TCTL_IO, 0) == -1) {
		printf("ThreadCtl\r\n");
		return (!EOK);
	}
	uintptr_t gpiobase;
	int result = InterruptAttach( IRQ_GPIO7_13, spi_intr, &gpiobase, sizeof(&gpiobase), _NTO_INTR_FLAGS_PROCESS);

	if(result == -1)
	{
		if (errno == EAGAIN)
		{
			printf("Interrupt are in use\r\n");
		}else if (errno == EFAULT)
		{
			printf("A fault occurred when the kernel tried to access the buffers provided.\r\n");
		}else if (errno == EINVAL)
		{
			printf("The value of intr is not a valid interrupt number.\r\n");
		}else if (errno == EPERM)
		{
			printf("The process doesn't have I/O privileges.\r\n");
		}else{
			printf("WTF.\r\n");
		}
	}else
	{
		printf("Attached IRQ ID = %d\r\n", result);
	}
	// pin configuration ...

	gpiobase	= mmap_device_io( MX6X_GPIO_SIZE,	MX6X_GPIO7_BASE );
	uintptr_t iomuxbase	= mmap_device_io( MX6X_IOMUXC_SIZE,	MX6X_IOMUXC_BASE );

	// set Logic ONE to Pin #5
	out32( gpiobase + MX6X_GPIO_DR, in32(gpiobase + MX6X_GPIO_DR) | (1 << MY_PIN) );

	// set INPUT direction for Pin #5
	out32( gpiobase + MX6X_GPIO_GDIR, in32(gpiobase + MX6X_GPIO_GDIR) & ~(1 << MY_PIN) );
	// ... pin configuration

	// set Interrupt CONFIGURATION "Rising Enge" for Pin #5 (ICR1: 0-15), two bits per pin
	out32( gpiobase + MX6X_GPIO_ICR1, (in32(gpiobase + MX6X_GPIO_ICR1) & ~(0x11 << (MY_PIN*2))) | (0x11 << (MY_PIN*2)) );

	// clear Disregarding "Rising Enge" for Pin #5
	out32( gpiobase + MX6X_GPIO_EDR, in32(gpiobase + MX6X_GPIO_EDR) | (1 << MY_PIN) );
//	printf("IRQ registers has been configured :)\n");

	// set Interrupt ENABLED for Pin #5
	out32( gpiobase + MX6X_GPIO_IMR, in32(gpiobase + MX6X_GPIO_IMR) | (1 << MY_PIN) );

	out32( gpiobase + MX6X_GPIO_ISR, in32(gpiobase + MX6X_GPIO_ISR) | (1 << MY_PIN) );



	out32( iomuxbase + MX6X_IOMUX_SWMUX + (4 * SWMUX_GPIO_18), MUX_CTL_MUX_MODE_ALT5);
	out32( iomuxbase + MX6X_IOMUX_SWPAD + (4 * SWPAD_GPIO_18), GPIO_PAD_INPUT);

	InterruptEnable();

	while(1)
	{
#if 0
		if ( !(in32(gpiobase + MX6X_GPIO_PSR) & (1 << MY_PIN)) )
		{
			spi_intr(NULL, 0);
		}

		#endif
		out32( gpiobase + MX6X_GPIO_IMR, in32(gpiobase + MX6X_GPIO_IMR) & ~(1 << MY_PIN) );
		if(count != count_last)
		{
			count_last = count;
			printf("\tPRESSED - %u times\n", count);
		}
		out32( gpiobase + MX6X_GPIO_IMR, in32(gpiobase + MX6X_GPIO_IMR) | (1 << MY_PIN) );
		delay(10);

	}

	return EXIT_SUCCESS;
}

static const struct sigevent *spi_intr(void *area, int id)
{
	count++;

	return NULL;
}