Browse Source

bug correction: retry reading values if i2c read was unsuccessfull, do not loose interuption added files for AXP209 interrupt started mapping axp209 interrupt

Vincent-FK 4 years ago
parent
commit
1aaecc7c3e
12 changed files with 233 additions and 86 deletions
  1. 1 1
      Makefile
  2. 71 0
      driver_axp209.c
  3. 31 0
      driver_axp209.h
  4. BIN
      driver_axp209.o
  5. 16 8
      driver_pcal6416a.c
  6. 6 6
      driver_pcal6416a.h
  7. BIN
      driver_pcal6416a.o
  8. BIN
      funkey_gpio_management
  9. 1 28
      gpio-utils.c
  10. 105 41
      gpio_mapping.c
  11. 2 2
      gpio_mapping.h
  12. BIN
      gpio_mapping.o

+ 1 - 1
Makefile

@@ -4,7 +4,7 @@ TOOLS_CFLAGS	:= -Wall -std=c99 -D _DEFAULT_SOURCE
 #
 all:	funkey_gpio_management 
 
-funkey_gpio_management:  funkey_gpio_management.o gpio-utils.o uinput.o gpio_mapping.o read_conf_file.o keydefs.o driver_pcal6416a.o smbus.o
+funkey_gpio_management:  funkey_gpio_management.o gpio-utils.o uinput.o gpio_mapping.o read_conf_file.o keydefs.o driver_pcal6416a.o driver_axp209.o smbus.o
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
 
 

+ 71 - 0
driver_axp209.c

@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <linux/input.h>
+#include "read_conf_file.h"
+#include <assert.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include "smbus.h"
+#include "driver_axp209.h"
+
+/****************************************************************
+ * Defines
+ ****************************************************************/
+#define DEBUG_AXP209_PRINTF 			(1)
+
+#if (DEBUG_AXP209_PRINTF)
+	#define DEBUG_PRINTF(...) printf(__VA_ARGS__);
+#else
+	#define DEBUG_PRINTF(...)
+#endif
+
+/****************************************************************
+ * Static variables
+ ****************************************************************/
+static int fd_axp209;
+static char i2c0_sysfs_filename[] = "/dev/i2c-0";
+
+/****************************************************************
+ * Static functions
+ ****************************************************************/
+
+/****************************************************************
+ * Public functions
+ ****************************************************************/
+bool axp209_init(void) {
+    if ((fd_axp209 = open(i2c0_sysfs_filename,O_RDWR)) < 0) {
+        printf("In axp209_init - Failed to open the I2C bus %s", i2c0_sysfs_filename);
+        // ERROR HANDLING; you can check errno to see what went wrong 
+        return false;
+    }
+
+    if (ioctl(fd_axp209, I2C_SLAVE, AXP209_I2C_ADDR) < 0) {
+        printf("In axp209_init - Failed to acquire bus access and/or talk to slave.\n");
+        // ERROR HANDLING; you can check errno to see what went wrong 
+        return false;
+    }
+
+ 	return true;
+}
+
+bool axp209_deinit(void) {
+    // Close I2C open interface
+	close(fd_axp209);
+ 	return true;
+}
+
+int axp209_read_interrupt_bank_3(void){
+	int val = i2c_smbus_read_byte_data ( fd_axp209 , AXP209_INTERRUPT_BANK_3_STATUS );
+    if(val < 0){
+        return val;
+    }
+ 	DEBUG_PRINTF("READ AXP209_INTERRUPT_BANK_3_STATUS:  0x%02X\n",val);
+ 	return 0xFF & val;
+}

+ 31 - 0
driver_axp209.h

@@ -0,0 +1,31 @@
+#ifndef _DRIVER_AXP209_H_
+#define _DRIVER_AXP209_H_
+
+
+ /****************************************************************
+ * Includes
+ ****************************************************************/
+#include <stdbool.h>
+
+ /****************************************************************
+ * Defines
+ ****************************************************************/
+// Chip physical address
+#define AXP209_I2C_ADDR			0x34
+
+// Chip registers adresses
+#define AXP209_INTERRUPT_BANK_3_STATUS		0x4A 
+
+// Masks
+#define AXP209_INTERRUPT_PEK_SHORT_PRESS	0x02 
+#define AXP209_INTERRUPT_PEK_LONG_PRESS		0x01 
+
+/****************************************************************
+ * Public functions
+ ****************************************************************/
+bool axp209_init(void);
+bool axp209_deinit(void);
+int axp209_read_interrupt_bank_3(void);
+
+
+#endif	//_DRIVER_AXP209_H_

BIN
driver_axp209.o


+ 16 - 8
driver_pcal6416a.c

@@ -29,8 +29,8 @@
 /****************************************************************
  * Static variables
  ****************************************************************/
-int fd_i2c_expander;
-char i2c0_sysfs_filename[] = "/dev/i2c-0";
+static int fd_i2c_expander;
+static char i2c0_sysfs_filename[] = "/dev/i2c-0";
 
 /****************************************************************
  * Static functions
@@ -67,15 +67,23 @@ bool pcal6416a_deinit(void) {
  	return true;
 }
 
-uint16_t pcal6416a_read_mask_interrupts(void){
-	uint16_t val = i2c_smbus_read_word_data ( fd_i2c_expander , PCAL6416A_INT_STATUS );
+int pcal6416a_read_mask_interrupts(void){
+	int val_int = i2c_smbus_read_word_data ( fd_i2c_expander , PCAL6416A_INT_STATUS );
+    if(val_int < 0){
+        return val_int;
+    }
+    uint16_t val = val_int & 0xFFFF;
  	DEBUG_PRINTF("READ PCAL6416A_INT_STATUS :  0x%04X\n",val);
- 	return val;
+ 	return (int) val;
 }
 
-uint16_t pcal6416a_read_mask_active_GPIOs(void){
-	uint16_t val = i2c_smbus_read_word_data ( fd_i2c_expander , PCAL6416A_INPUT );
+int pcal6416a_read_mask_active_GPIOs(void){
+	int val_int = i2c_smbus_read_word_data ( fd_i2c_expander , PCAL6416A_INPUT );
+    if(val_int < 0){
+        return val_int;
+    }
+    uint16_t val = val_int & 0xFFFF;
 	val = 0xFFFF-val;
  	DEBUG_PRINTF("READ PCAL6416A_INPUT (active GPIOs) :  0x%04X\n",val);
- 	return val;
+ 	return (int) val;
 }

+ 6 - 6
driver_pcal6416a.h

@@ -14,16 +14,16 @@
 #define PCAL6416A_I2C_ADDR			0x20
 
 // Chip registers adresses
-#define PCAL6416A_INPUT			0x00 /* Input port [RO] */
+#define PCAL6416A_INPUT				0x00 /* Input port [RO] */
 #define PCAL6416A_DAT_OUT      		0x02 /* GPIO DATA OUT [R/W] */
 #define PCAL6416A_POLARITY     		0x04 /* Polarity Inversion port [R/W] */
 #define PCAL6416A_CONFIG       		0x06 /* Configuration port [R/W] */
-#define PCAL6416A_DRIVE0		0x40 /* Output drive strength Port0 [R/W] */
-#define PCAL6416A_DRIVE1		0x42 /* Output drive strength Port1 [R/W] */
+#define PCAL6416A_DRIVE0			0x40 /* Output drive strength Port0 [R/W] */
+#define PCAL6416A_DRIVE1			0x42 /* Output drive strength Port1 [R/W] */
 #define PCAL6416A_INPUT_LATCH		0x44 /* Port0 Input latch [R/W] */
 #define PCAL6416A_EN_PULLUPDOWN		0x46 /* Port0 Pull-up/Pull-down enbl [R/W] */
 #define PCAL6416A_SEL_PULLUPDOWN	0x48 /* Port0 Pull-up/Pull-down slct [R/W] */
-#define PCAL6416A_INT_MASK		0x4A /* Interrupt mask [R/W] */ 
+#define PCAL6416A_INT_MASK			0x4A /* Interrupt mask [R/W] */ 
 #define PCAL6416A_INT_STATUS		0x4C /* Interrupt status [RO] */ 
 #define PCAL6416A_OUTPUT_CONFIG 	0x4F /* Output port config [R/W] */ 
 
@@ -32,8 +32,8 @@
  ****************************************************************/
 bool pcal6416a_init(void);
 bool pcal6416a_deinit(void);
-uint16_t pcal6416a_read_mask_interrupts(void);
-uint16_t pcal6416a_read_mask_active_GPIOs(void);
+int pcal6416a_read_mask_interrupts(void);
+int pcal6416a_read_mask_active_GPIOs(void);
 
 
 #endif	//_DRIVER_PCAL6416A_H_

BIN
driver_pcal6416a.o


BIN
funkey_gpio_management


+ 1 - 28
gpio-utils.c

@@ -1,33 +1,6 @@
-/* Copyright (c) 2011, RidgeRun
+/* Copyright (c) 2019 FunKey
  * All rights reserved.
  *
-From https://www.ridgerun.com/developer/wiki/index.php/Gpio-int-test.c
-
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    This product includes software developed by the RidgeRun.
- * 4. Neither the name of the RidgeRun nor the
- *    names of its contributors may be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY RIDGERUN ''AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL RIDGERUN BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "gpio-utils.h"

+ 105 - 41
gpio_mapping.c

@@ -12,6 +12,7 @@
 #include <linux/input.h>
 #include "gpio_mapping.h"
 #include "driver_pcal6416a.h"
+#include "driver_axp209.h"
 
 /****************************************************************
  * Defines
@@ -21,7 +22,7 @@
         return(EXIT_FAILURE); \
     } while(0)
 
-#define DEBUG_GPIO_PRINTF 			(0)
+#define DEBUG_GPIO_PRINTF 			(1)
 #define ERROR_GPIO_PRINTF 			(1)
 
 #if (DEBUG_GPIO_PRINTF)
@@ -40,6 +41,9 @@
 // If not declared, there will be no timeout and no periodical sanity check of GPIO expander values
 #define TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP	2
 
+// This is for debug purposes on cards or eval boards that do not have the AXP209
+//#define ENABLE_AXP209_INTERRUPTS
+
 
 /****************************************************************
  * Static variables
@@ -48,9 +52,12 @@ static int nb_mapped_gpios;
 static int * gpio_pins;
 STRUCT_MAPPED_GPIO * chained_list_mapping;
 static int max_fd = 0;
-static int gpio_fd_interrupt_i2c;
+static int gpio_fd_interrupt_expander_gpio;
+static int gpio_fd_interrupt_axp209;
 static fd_set fds;
 static bool * mask_gpio_value;
+static bool interrupt_i2c_expander_found = false;
+static bool interrupt_axp209_found = false;
 
 
 /****************************************************************
@@ -178,37 +185,37 @@ static void find_and_call_mapping_function(int idx_gpio_interrupted,
 }
 
 /*****  Init GPIO Interrupt i2c expander fd  *****/
-static int init_gpio_interrupt(void)
+static int init_gpio_interrupt(int pin_nb, int *fd_saved)
 {
   	// Variables
-  	int cur_pin_nb = GPIO_PIN_I2C_EXPANDER_INTERRUPT;
-  	GPIO_PRINTF("Initializing Interrupt i2c expander GPIO pin fd: %d\n", cur_pin_nb);
+  	GPIO_PRINTF("Initializing Interrupt on GPIO pin: %d\n", pin_nb);
 	  
 	// Init fds fd_set 
 	FD_ZERO(&fds);
 	  
 	//Initializing I2C interrupt GPIO
-	gpio_export(cur_pin_nb); 
+	gpio_export(pin_nb); 
 	//gpio_set_edge(cur_pin_nb, "both");  // Can be rising, falling or both
-	gpio_set_edge(cur_pin_nb, "falling");  // Can be rising, falling or both
-	gpio_fd_interrupt_i2c = gpio_fd_open(cur_pin_nb, O_RDONLY);
+	gpio_set_edge(pin_nb, "falling");  // Can be rising, falling or both
+	*fd_saved = gpio_fd_open(pin_nb, O_RDONLY);
+  	GPIO_PRINTF("fd is: %d\n", *fd_saved);
 		
 	// add stdin and the sock fd to fds fd_set 
-	safe_fd_set(gpio_fd_interrupt_i2c, &fds, &max_fd);
+	safe_fd_set(*fd_saved, &fds, &max_fd);
 
 	return 0;
 }
 
 /*****  DeInit GPIO Interrupt i2c expander fd  *****/
-static int deinit_gpio_interrupt(void)
+static int deinit_gpio_interrupt(int fd_saved)
 { 
-  	GPIO_PRINTF("DeInitializing Interrupt i2c expander GPIO pin fd\n");
+  	GPIO_PRINTF("DeInitializing Interrupt on GPIO pin fd: %d\n", fd_saved);
 
 	// Remove stdin and  sock fd from fds fd_set 
-	safe_fd_clr(gpio_fd_interrupt_i2c, &fds, &max_fd);
+	safe_fd_clr(fd_saved, &fds, &max_fd);
 	
 	// Unexport GPIO
-	gpio_fd_close(gpio_fd_interrupt_i2c);
+	gpio_fd_close(fd_saved);
 
 	return 0;
 }
@@ -242,12 +249,22 @@ int init_mapping_gpios(int * gpio_pins_to_declare, int nb_gpios_to_declare,
 		current = current->next_mapped_gpio;
 	} while(current != NULL);
 
-	// Init GPIO interrupt from I2C expander
-	init_gpio_interrupt();
+	// Init GPIO interrupt from I2C GPIO expander
+	GPIO_PRINTF("	Initiating interrupt for GPIO_PIN_I2C_EXPANDER_INTERRUPT\n");
+	init_gpio_interrupt(GPIO_PIN_I2C_EXPANDER_INTERRUPT, &gpio_fd_interrupt_expander_gpio);
 
 	// Init I2C expander
 	pcal6416a_init();
 
+#ifdef ENABLE_AXP209_INTERRUPTS
+	// Init GPIO interrupt from AXP209
+	GPIO_PRINTF("	Initiating interrupt for GPIO_PIN_AXP209_INTERRUPT\n");
+	init_gpio_interrupt(GPIO_PIN_AXP209_INTERRUPT, &gpio_fd_interrupt_axp209);
+
+	// Init AXP209
+	axp209_init();
+#endif //ENABLE_AXP209_INTERRUPTS
+
 	return 0;
 }
 
@@ -255,10 +272,21 @@ int init_mapping_gpios(int * gpio_pins_to_declare, int nb_gpios_to_declare,
 int deinit_mapping_gpios(void)
 {
 	// DeInit GPIO interrupt from I2C expander
-	deinit_gpio_interrupt();
+	GPIO_PRINTF("	DeInitiating interrupt for GPIO_PIN_I2C_EXPANDER_INTERRUPT\n");
+	deinit_gpio_interrupt(gpio_fd_interrupt_expander_gpio);
 
 	// DeInit I2C expander
 	pcal6416a_deinit();
+
+#ifdef ENABLE_AXP209_INTERRUPTS
+	// DeInit GPIO interrupt from AXP209
+	GPIO_PRINTF("	DeInitiating interrupt for GPIO_PIN_AXP209_INTERRUPT\n");
+	deinit_gpio_interrupt(gpio_fd_interrupt_axp209);
+
+	// DeInit AXP209
+	axp209_deinit();
+#endif //ENABLE_AXP209_INTERRUPTS
+
 	return 0;
 }
 
@@ -267,12 +295,11 @@ int deinit_mapping_gpios(void)
 int listen_gpios_interrupts(void)
 {
 	// Variables
-	char buffer[2];
-	int idx_gpio, value;
+	//char buffer[2];
+	//int value;
+	int idx_gpio;
 	bool previous_mask_gpio_value[nb_mapped_gpios];
 	bool mask_gpio_current_interrupts[nb_mapped_gpios];
-	uint16_t val_i2c_mask_interrupted, val_i2c_mask_active;
-	bool interrupt_found = false;
 
 	// Back up master 
 	fd_set dup = fds;
@@ -282,29 +309,31 @@ int listen_gpios_interrupts(void)
 	memset(mask_gpio_value, false, nb_mapped_gpios*sizeof(bool));
 	memset(mask_gpio_current_interrupts, false, nb_mapped_gpios*sizeof(bool));
 
-	// Waiting for interrupt or timeout, Note the max_fd+1
+	// If interrupt not already found, waiting for interrupt or timeout, Note the max_fd+1
+	if(!interrupt_i2c_expander_found && !interrupt_axp209_found){
 #ifdef TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP
-	struct timeval timeout = {TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP, 0};
-	int nb_interrupts = select(max_fd+1, NULL, NULL, &dup, &timeout);
+		struct timeval timeout = {TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP, 0};
+		int nb_interrupts = select(max_fd+1, NULL, NULL, &dup, &timeout);
 #else
-	int nb_interrupts = select(max_fd+1, NULL, NULL, &dup, NULL);
+		int nb_interrupts = select(max_fd+1, NULL, NULL, &dup, NULL);
 #endif //TIMEOUT_SEC_SANITY_CHECK_GPIO_EXP
-	if(!nb_interrupts){
-		// Timeout case 
-		GPIO_PRINTF("	Timeout, forcing sanity check\n");
-		// Timeout forcing a "Found interrupt" event for sanity check
-		interrupt_found = true;
-	}
-	else if ( nb_interrupts < 0) {
-		perror("select");
-		return -1;
+		if(!nb_interrupts){
+			// Timeout case 
+			GPIO_PRINTF("	Timeout, forcing sanity check\n");
+			// Timeout forcing a "Found interrupt" event for sanity check
+			interrupt_i2c_expander_found = true;
+		}
+		else if ( nb_interrupts < 0) {
+			perror("select");
+			return -1;
+		}
 	}
 
-	// Check if interrupt from I2C expander
+	// Check if interrupt from I2C expander or AXP209
 	// Check which cur_fd is available for read 
 	for (int cur_fd = 0; cur_fd <= max_fd; cur_fd++) {
 		if (FD_ISSET(cur_fd, &dup)) {
-			// Revenir au debut du fichier (lectures successives).
+			/*// Rewind file
 			lseek(cur_fd, 0, SEEK_SET);
 			
 			// Read current gpio value
@@ -313,19 +342,54 @@ int listen_gpios_interrupts(void)
 				break;
 			}
 
-			// Effacer le retour-chariot.
+			// remove end of line char
 			buffer[1] = '\0';
-			value = 1-atoi(buffer);
+			value = 1-atoi(buffer);*/
 
 			// Found interrupt
-			interrupt_found = true;
+			if(cur_fd == gpio_fd_interrupt_expander_gpio){
+				interrupt_i2c_expander_found = true;
+			}
+			else if(cur_fd == gpio_fd_interrupt_axp209){
+				interrupt_axp209_found = true;
+			}
 		}
 	}
 
-	if(interrupt_found){
+
+#ifdef ENABLE_AXP209_INTERRUPTS
+	if(interrupt_axp209_found){
+		GPIO_PRINTF("	Found interrupt AXP209\n");
+		int val_int_bank_3 = axp209_read_interrupt_bank_3();
+		if(val_int_bank_3 < 0){
+			GPIO_PRINTF("	Could not read AXP209 with I2C\n");
+			return 0;
+		}
+		interrupt_axp209_found = false;
+
+		if(val_int_bank_3 & AXP209_INTERRUPT_PEK_SHORT_PRESS){
+			GPIO_PRINTF("	AXP209 short PEK key press detected\n");
+		}
+		if(val_int_bank_3 & AXP209_INTERRUPT_PEK_LONG_PRESS){
+			GPIO_PRINTF("	AXP209 long PEK key press detected\n");
+		}
+	}
+#endif //ENABLE_AXP209_INTERRUPTS
+
+	if(interrupt_i2c_expander_found){
 		// Read I2C GPIO masks: 
-		val_i2c_mask_interrupted = pcal6416a_read_mask_interrupts();
-		val_i2c_mask_active = pcal6416a_read_mask_active_GPIOs();
+		int val_i2c_mask_interrupted = pcal6416a_read_mask_interrupts();
+		if(val_i2c_mask_interrupted < 0){
+			GPIO_PRINTF("	Could not read pcal6416a_read_mask_interrupts\n");
+			return 0;
+		}
+		int val_i2c_mask_active = pcal6416a_read_mask_active_GPIOs();
+		if(val_i2c_mask_active < 0){
+			GPIO_PRINTF("	Could not read pcal6416a_read_mask_active_GPIOs\n");
+			return 0;
+		}
+		interrupt_i2c_expander_found = false;
+
 
 		// Find GPIO idx correspondance
 		for (idx_gpio=0; idx_gpio<nb_mapped_gpios; idx_gpio++){

+ 2 - 2
gpio_mapping.h

@@ -11,8 +11,8 @@
 /****************************************************************
 * Defines
 ****************************************************************/
-#define GPIO_PIN_I2C_EXPANDER_INTERRUPT	35			//PB3
-//#define GPIO_PIN_I2C_EXPANDER_INTERRUPT	38			//PB6
+#define GPIO_PIN_I2C_EXPANDER_INTERRUPT		35			//PB3
+#define GPIO_PIN_AXP209_INTERRUPT			37			//PB5
 
 /****************************************************************
 * Public functions

BIN
gpio_mapping.o