Alessandro Benini
|
Interrupt management on Beaglebone running QNX 6.5
|
Alessandro Benini
09/25/2013 4:36 PM
post105406
|
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++;
}
}
|
|
|
Yaroslav Stetsyk(deleted)
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Yaroslav Stetsyk(deleted)
12/11/2013 9:37 AM
post107401
|
Re: Interrupt management on Beaglebone running QNX 6.5
Hi!
What does it mean:
out32(ptr2 + GPIO_OE,(1 << 12));
???
|
|
|
Alessandro Benini
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Alessandro Benini
12/11/2013 10:12 AM
post107405
|
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.
|
|
|
Yaroslav Stetsyk(deleted)
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Yaroslav Stetsyk(deleted)
12/11/2013 11:20 AM
post107411
|
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?
|
|
|
Yaroslav Stetsyk(deleted)
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Yaroslav Stetsyk(deleted)
12/11/2013 11:27 AM
post107413
|
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.
|
|
|
Alessandro Benini
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Alessandro Benini
12/11/2013 1:27 PM
post107422
|
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.
|
|
|
Yaroslav Stetsyk(deleted)
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Yaroslav Stetsyk(deleted)
12/12/2013 11:28 AM
post107472
|
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!
|
|
|
Alessandro Benini
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Alessandro Benini
12/12/2013 11:42 AM
post107473
|
Re: Interrupt management on Beaglebone running QNX 6.5
Yes, Thanks!
My email is alessandro [dot] nuke [@] gmail [dot] com
|
|
|
Alessandro Benini
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Alessandro Benini
12/12/2013 11:50 AM
post107474
|
Re: Interrupt management on Beaglebone running QNX 6.5
My email is: alessandro.nuke@gmail.com.
Thanks for sharing your code!
Alessandro
|
|
|
Yaroslav Stetsyk(deleted)
|
Re: Interrupt management on Beaglebone running QNX 6.5
|
Yaroslav Stetsyk(deleted)
12/12/2013 12:00 PM
post107477
|
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;
}
|
|
|
|