I'm running on Imx6dq
I'v wrote simple char device and I configured gpio1_1 operate as an interrupt
here is my code
my issue is that the isr is been call more the 1 since it not ack
what I'm doing wrong
Thanks
/*
//Taken from https://stackoverflow.com/questions/15215865/netlink-sockets-in-c-using-the-3-x-linux-kernel?lq=1
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/time.h>
#include <stddef.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/irq.h>
#include <asm/irq.h>//#include <stdlib.h>
#include <asm/gpio.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
//#include <mach/hardware.h>
#include <asm/gpio.h>
#define __WORDSIZE 0
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
/* Unsigned. */
typedef unsigned char uint_fast8_t;
#if __WORDSIZE == 64
typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long int uint_fast64_t;
#else
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
__extension__
typedef unsigned long long int uint_fast64_t;
#endif
#define FUNC_GPIO 0x5
#define MAX_SIZE (PAGE_SIZE * 2) /* max size mmaped to userspace */
#define NETLINK_USER 31
static char *sh_mem = NULL;
struct sock *nl_sk = NULL;
struct timeval tvStart ;
struct timeval tvStop ;
//float f1 ;
unsigned int base_addr = 0x02000000;
unsigned int base_offs = 0x00000000;
void* gpioAddr = 0 ;
ssize_t page_size = (1024*1024);
enum function_t {
FUNCTION_UNKNOWN = 0,
FUNCTION_DIGITAL = 2,
FUNCTION_ANALOG = 4,
FUNCTION_I2C = 16,
FUNCTION_INTERRUPT = 32
};
enum pinmode_t {
PINMODE_NOT_SET = 0,
PINMODE_INPUT = 2,
PINMODE_OUTPUT = 4,
PINMODE_INTERRUPT = 8
};
enum isr_mode_t {
ISR_MODE_UNKNOWN = 0,
ISR_MODE_RISING = 2,
ISR_MODE_FALLING = 4,
ISR_MODE_BOTH = 8,
ISR_MODE_NONE = 16
};
enum isr_mode_t_driver
{
LOW_LEVEL = 0x00 , //LOW_LEVEL — Interrupt n is low-level sensitive.
HIGH_LEVEL = 0x01 , //HIGH_LEVEL — Interrupt n is high-level sensitive.
RISING_EDGE = 0x10 , //RISING_EDGE — Interrupt n is rising-edge sensitive.
FALLING_EDGE = 0x11 , //FALLING_EDGE — Interrupt n is falling-edge sensitive.
};
enum pud
{
// Pull up/down/none
PUD_OFF = 0 ,
PUD_DOWN = 1 ,
PUD_UP = 2
};
enum intMask
{
MASK = 0 ,
UNMASK = 1 ,
};
enum digital_value_t {
LOW,
HIGH
};
enum gpioRegOffset {
DR = 0x0 , // Data Register
GDIR = 0x4 , // Direction Register
PSR = 0x8 , // Status Register
ICR1 = 0xC , // Interrupt Configuration Register1
ICR2 = 0x10 , // Interrupt Configuration Register2
IMR = 0x14 , // Interrupt Mask Register
ISR = 0x18 , // Interrupt Status Register
EDGE_SEL = 0x1C , // Edge Select Register
};
void soc_writel(uintptr_t addr, uint32_t val)
{
writel(val, (volatile void *)addr );
}
uint32_t soc_readl(uintptr_t addr)
{
return readl((const volatile void *)addr);
}
#define RONENDEV_MAJOR 190
int irqNo = 0 ;
static int gpio_num;
DECLARE_COMPLETION(work);
int static counter = 0 ;
static irqreturn_t handler (int irq, void * dev)
{
void* addrDatISR = NULL ;//( gpioAddr + ISR );
void* addrDatStatus = NULL ;//( gpioAddr + PSR );
uint32_t valIMR = 0x2 ;
uint32_t valStatus = 0 ;
addrDatISR = (void*)( gpioAddr + 0x9C000 + ISR );//( gpioAddr + ISR ); valStatus = ioread32( addrDatStatus );
addrDatStatus = (void*)( gpioAddr + 0x9C000 + PSR );//( gpioAddr + PSR ); printk("Status 0x%08X Occurred aaa 0x%08lX\n" , valStatus, ( unsigned long ) addrDatISR );
valStatus = ioread32( addrDatStatus );
iowrite32( 0x02 , addrDatISR );
valStatus = ioread32( addrDatStatus );
complete_all(&work);
return IRQ_HANDLED;
}
static int __init hello_init(void)
{
int status;
printk("Entering: %s\n",__FUNCTION__);
gpioAddr = ioremap( 0x2000000 , page_size );
if( gpioAddr )
printk("success to virutal mem \n");
init_completion(&work);
gpio_num = 1;
status = gpio_request(gpio_num, "gpio_test\n");
if (status < 0)
{
printk("ERROR can not open GPIO %d\n", gpio_num);
return status;
}
gpio_direction_input(gpio_num);
gpio_export(gpio_num, true);
if(gpio_get_value(gpio_num) == 0)
printk("OFF. \n\tWaiting for the pin to be on..\n");
else
printk("ON. \n\tWaiting for the pin to be off..\n");
irqNo = gpio_to_irq(gpio_num);
printk("gpio %d has irq %d \n" , gpio_num , irqNo );
status = request_irq(irqNo, handler, 0, "gpio_test", NULL);
if(status < 0)
{
printk(KERN_ERR "error %d requesting GPIO IRQ %d\n", status, gpio_num);
return status;
}
irq_set_irq_type(irqNo, IRQ_TYPE_EDGE_RISING);
wait_for_completion_interruptible(&work);
printk(".. done counter %d \n");
return 0;
}
static void __exit hello_exit(void)
{
free_irq(gpio_to_irq(gpio_num), NULL);
gpio_free(gpio_num);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
Hi Ronen
for gpio interrupt one can look at touchscreen drivers examples, like
[v2,1/2] Input: egalax_ts: get gpio from devicetree node - Patchwork
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hello Igor
Thanks for the answer
but I'm still dont understand how the interrupt cleared at the ISR .
My issue is that the ISR is been called many times