I am creating a kernel module device driver to work with GPIOs. I have spent a lot of time but still cannot figure out what is wrong with GPIO reading.
Setting and clearing GPIO works perfectly.
Here is my header file with all constants and macroses.
/*! This means pin HIGH, true, 3.3volts on a pin. */
#define HIGH 0x1
/*! This means pin LOW, false, 0volts on a pin. */
#define LOW 0x0
// ------ BCM2835 CONFIGURATION -----
#define BCM2835_GPFSEL0 0x0000 /*!< GPIO Function Select 0 */
#define BCM2835_GPFSEL1 0x0004 /*!< GPIO Function Select 1 */
#define BCM2835_GPFSEL2 0x0008 /*!< GPIO Function Select 2 */
#define BCM2835_GPFSEL3 0x000c /*!< GPIO Function Select 3 */
#define BCM2835_GPFSEL4 0x0010 /*!< GPIO Function Select 4 */
#define BCM2835_GPFSEL5 0x0014 /*!< GPIO Function Select 5 */
#define BCM2835_GPSET0 0x001c /*!< GPIO Pin Output Set 0 */
#define BCM2835_GPSET1 0x0020 /*!< GPIO Pin Output Set 1 */
#define BCM2835_GPCLR0 0x0028 /*!< GPIO Pin Output Clear 0 */
#define BCM2835_GPCLR1 0x002c /*!< GPIO Pin Output Clear 1 */
#define BCM2835_GPLEV0 0x0034 /*!< GPIO Pin Level 0 */
#define BCM2835_GPLEV1 0x0038 /*!< GPIO Pin Level 1 */
#define BCM2835_GPEDS0 0x0040 /*!< GPIO Pin Event Detect Status 0 */
#define BCM2835_GPEDS1 0x0044 /*!< GPIO Pin Event Detect Status 1 */
#define BCM2835_GPREN0 0x004c /*!< GPIO Pin Rising Edge Detect Enable 0 */
#define BCM2835_GPREN1 0x0050 /*!< GPIO Pin Rising Edge Detect Enable 1 */
#define BCM2835_GPFEN0 0x0058 /*!< GPIO Pin Falling Edge Detect Enable 0 */
#define BCM2835_GPFEN1 0x005c /*!< GPIO Pin Falling Edge Detect Enable 1 */
#define BCM2835_GPHEN0 0x0064 /*!< GPIO Pin High Detect Enable 0 */
#define BCM2835_GPHEN1 0x0068 /*!< GPIO Pin High Detect Enable 1 */
#define BCM2835_GPLEN0 0x0070 /*!< GPIO Pin Low Detect Enable 0 */
#define BCM2835_GPLEN1 0x0074 /*!< GPIO Pin Low Detect Enable 1 */
#define BCM2835_GPAREN0 0x007c /*!< GPIO Pin Async. Rising Edge Detect 0 */
#define BCM2835_GPAREN1 0x0080 /*!< GPIO Pin Async. Rising Edge Detect 1 */
#define BCM2835_GPAFEN0 0x0088 /*!< GPIO Pin Async. Falling Edge Detect 0 */
#define BCM2835_GPAFEN1 0x008c /*!< GPIO Pin Async. Falling Edge Detect 1 */
#define BCM2835_GPPUD 0x0094 /*!< GPIO Pin Pull-up/down Enable */
#define BCM2835_GPPUDCLK0 0x0098 /*!< GPIO Pin Pull-up/down Enable Clock 0 */
#define BCM2835_GPPUDCLK1 0x009c /*!< GPIO Pin Pull-up/down Enable Clock 1 */
#define BCM2835_PERI_BASE 0x3F000000
#define GPIO_BASE (BCM2835_PERI_BASE + 0x200000) // GPIO controller
#define INP_GPIO(g) *(gpio.addr +((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio.addr+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio.addr+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET *(gpio.addr+7) // sets bits which are 1 ignores bits which are 0
#define GPIO_CLR *(gpio.addr+10) // clears bits which are 1 ignores bits which are 0
#define GET_GPIO(g) (*(gpio.addr + BCM2835_GPLEV0/4)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
#define GPIO_PULL *(gpio.addr+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio.addr+38) // Pull up/pull down clock
struct bcm2835_peripheral {
unsigned long addr_p;
int mem_fd;
void *map;
volatile unsigned int *addr;
};
struct bcm2835_peripheral gpio = {GPIO_BASE};
// ********* GPIO Support ************
#define MOTION_SENSOR_PIN 12
#define MOTION_DRIVER_DEVICE_NAME "motionDetector"
Here is the initialisation of GPIO
gpio.map = ioremap(GPIO_BASE, 4096);
gpio.addr = (volatile unsigned int *)gpio.map;
printk("module gpio : MOTION GPIO Init\n");
INP_GPIO(MOTION_SENSOR_PIN);
And I am trying to read the value like that
motion_value = GET_GPIO(MOTION_SENSOR_PIN);
It always returns 0, however if my PIN number is set to 12 as in the code above. It reads the value of 4096. I guess this is 2^12, that's fine I can & or | it to find out whether the level is high or low.
But the problem is that in case I use the PIN 21 or any other, it always returns 0. Of course I reconnected my sensor to this pin.
What could be wrong with my code ? Why doesn't it work ?
Using wiringpi, bcm2835 library and other it works well.
I would be grateful for any help.