Gestion interrupt entre mcp23017 et esp32

Bonjour à tous,
Je m'arrache les cheveux pour tenter d'intercepter les IT d'un MCP23017 sur ESP32.
Dès que je tente de capter l'interruption du MCP (qui fonctionne très bien en pooling dans le loop) dans un IRAM_ATTR, l'ESP reboot !
Bizarement, je n'ai trouvé aucun exemple de gestion des it par l'ESP sur le net ?
Je voudrais éviter un pooling dans le loop.
J'ai également essayé avec freetos mais idem !
Si quelqu'un à une idée.

Postez le code et le schéma du circuit avec les alimentations

Voici le schéma en pdf
Sheet4.pdf (162.8 KB)
le code:


```cpp

#include <Adafruit_MCP23X17.h>
#include "Wire.h"

const byte interruptPin = 25;  // microcontroller pin attached to INTA/B
int but;
int butn;
int nbut;
Adafruit_MCP23X17 mcp;

void IRAM_ATTR handleInterrupt() {
  mcp.clearInterrupts();                                //clear IT mcp
  detachInterrupt(digitalPinToInterrupt(interruptPin)); //on invalide les IT ESP pendant traitement IT
  itt();                                                //vers traitement IT
}

void setup() {
  Wire.begin();
  Serial.begin(115200);
  if (!mcp.begin_I2C()) {
    Serial.println("Erreur mcp");
    while (1);
  }
  for (int i = 0; i < 3; i++) {
    mcp.pinMode(i, INPUT_PULLUP);  //on met les pins 0 à 3 en input avec pullup
    delay(50);
    mcp.setupInterruptPin(i, LOW);  //on met les pins 0 à 3 en IT sur niveau bas
    delay(50);
  }
  mcp.setupInterrupts(true, true, LOW);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
  Serial.println("FIN SETUP");
}
//traitement IT
void itt() {
  but = mcp.getLastInterruptPin();  //on stocke la touche actuelle   
  mcp.disableInterruptPin(but);     //on interdit l'IT de la pin actuelle
  mcp.setupInterruptPin(butn, LOW); //on restaure l'IT de la pin précédente
  butn = but;                       //pour mémoriser la touche actuelle
  mcp.clearInterrupts();            // clear IT
  Serial.print("DSB int on pin: "); //affichage de la touche actuelle
  Serial.println(but);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING); //on ré-autorise les IT ESP
}
void loop() {

  if (!digitalRead(interruptPin)) itt();    //pour test
}

puis le dump au reboot:

Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1). 

Core  1 register dump:
PC      : 0x4008afde  PS      : 0x00060735  A0      : 0x80089f56  A1      : 0x3ffbef4c  
A2      : 0x3ffc55d0  A3      : 0x3ffbd6a4  A4      : 0x00000004  A5      : 0x00060723  
A6      : 0x00060723  A7      : 0x00000001  A8      : 0x3ffbd6a4  A9      : 0x00000018  
A10     : 0x3ffbd6a4  A11     : 0x00000018  A12     : 0x3ffc246c  A13     : 0x00060723  
A14     : 0x007bf388  A15     : 0x003fffff  SAR     : 0x00000007  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x40086228  LEND    : 0x4008623e  LCOUNT  : 0x00000000  
Core  1 was running in ISR context:
EPC1    : 0x400ddc9f  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x00000000
A14     : 0x007bf388  A15     : 0x003fffff  SAR     : 0x00000007  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x40086228  LEND    : 0x4008623e  LCOUNT  : 0x00000000  
Core  1 was running in ISR context:
EPC1    : 0x400ddc9f  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x00000000


Backtrace: 0x4008afdb:0x3ffbef4c |<-CORRUPTED


Core  0 register dump:
PC      : 0x4008b17b  PS      : 0x00060035  A0      : 0x80089b7f  A1      : 0x3ffbeaac  
A2      : 0x3ffbf388  A3      : 0xb33fffff  A4      : 0x0000abab  A5      : 0x00060023  
A6      : 0x00060021  A7      : 0x0000cdcd  A8      : 0x0000abab  A9      : 0xffffffff  
A10     : 0x3ffc2288  A11     : 0x00000000  A12     : 0x3ffc2284  A13     : 0x00000007  
A14     : 0x007bf388  A15     : 0x003fffff  SAR     : 0x0000001d  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000  


Backtrace: 0x4008b178:0x3ffbeaac |<-CORRUPTED




ELF file SHA256: ef55b2e3d1ed907e

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13260
load:0x40080400,len:3028
entry 0x400805e4
FIN SETUP

Votre fonction itt() appelée depuis l’interruption doit aussi être en IRAM_ATTR

Bonsoir

te recherche ne t'as pas conduit jusqu'à l'excellent site Random Nerd Tutorials ? (souvent copié , jamais égalé :wink:)

Bonjour,

Déjà, manipuler des enable/disable It dans une routine de traitement d'It est illisible, non déterministe et très dangereux...

De plus, une routine d'It doit se contenter de mettre en FIFO des événements pour les traces par exemple, copier des données, faire quelques I/O (Leds par exemple) et surtout positionner un flag qui, traité dans le loop, permettra de faire les traitements lourds hors It ... Au vu de la puissance d'un ESP32, il aura largement terminé lesdits traitements avant la prochaine "même" It

Pour finir, je ne fais jamais de Serial.xxx dans une routine d'interruption ... j'en sors le plus vite possible en qualifiant la durée de traitement et en vérifiant l'absence de réentrance pour anticiper au mieux des plantages et au pire des dysfonctionnements

NB: Sinon, jamais eu de problème avec les Its avec un ESP32 pour peu que l'on respecte les règles de bon sens :wink:

OK, grosse betise de ma part.
Merci à tous

Ce n’est pas toujours le cas et si c’est le cas autant faire du polling et ne pas utiliser les interruptions

Un Serial.print fait aussi cela… donc faut faire attention aussi à ce qui consomme la FIFO

C’était quoi la solution ?