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é
)
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 ![]()
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 ?