eloquentarduino/tflm_esp32

Calling invoke() encounters Guru Meditation Error on esp32

Closed this issue · 5 comments

I am currently working with your program and encountered a Guru Meditation Error after adding logging to the TfLiteStatus MicroInterpreterGraph::InvokeSubgraph(int subgraph_idx) function, specifically in the line:

TfLiteStatus MicroInterpreterGraph::InvokeSubgraph(int subgraph_idx) {
....
TfLiteStatus invoke_status = registration->invoke(context_, node);
....
}

Guru Meditation Error: Core 0 panic'ed (InstructionFetchError). Exception was unhandled.

Core 0 register dump:
PC : 0x3ffb6b3d PS : 0x00060f30 A0 : 0x80140e3d A1 : 0x3ffe2890
A2 : 0x3ffc6ed8 A3 : 0x00000000 A4 : 0x3ffd483c A5 : 0x3ffe2760
A6 : 0x00000000 A7 : 0x0000000b A8 : 0x801411c1 A9 : 0x00000000
A10 : 0x3ffc6e70 A11 : 0x3ffd483c A12 : 0x00000001 A13 : 0x00000000
A14 : 0x3ffb6884 A15 : 0x00000001 SAR : 0x00000004 EXCCAUSE: 0x00000002
EXCVADDR: 0x3ffb6b3c LBEG : 0x400899c0 LEND : 0x400899d6 LCOUNT : 0x00000000

Backtrace: 0x3ffb6b3a:0x3ffe2890 |<-CORRUPTED

I believe the error might be related to the function pointer registration->invoke, which seems to be pointing to an address that is causing the InstructionFetchError. However, I'm not entirely sure how to proceed with debugging this issue.

Could you please offer any advice on how to troubleshoot this problem? Have you encountered similar issues in your experience?

Thank you very much for your assistance and guidance. I greatly appreciate your help!

I don't understand what you're doing:

  • which topology does your network has?
  • how did you add logging?
  • are you using TF directly or throughout EloquentTinyML library?

I'm sorry, I didn't make myself clear.

  1. After converting the CNN to TFLite, open it with netron.app to see: input, ExpandDims, Conv2D, Reshape, MaxPool2D, ReduceMax and FullyConnected Layer.
    image

And I added the opresolver to the code.
image

2.Regarding the issue, I added printf() statements directly inside the Invoke() function to trace the execution step by step. The error appeared when I reached this line of code:
TfLiteStatus invoke_status = registration->invoke(context_, node);
The program printed the error right after this line, indicating that something might be going wrong with the function pointer or the invocation process.

  1. I’m only using the tflm_esp32 library available on PlatformIO.

The environment is
platformIO ver. = 6.1.15
Platform = espressif32
Espressif 32 version = 6.8.1
Board = esp32doit-devkit-v1
Framework = arduino
library = eloquentarduino/tflm_esp32@^2.0.0

Modeling:

def Build1DCNN(input_shape, classes):
    # Initialize the model
    model = models.Sequential()
    model.add(Input(shape=input_shape))
    
    # First convolutional layer
    model.add(Conv1D(filters=16, kernel_size=5, activation="relu")) 
    model.add(MaxPooling1D(2))  # default pool_size=2
    
    # Second convolutional layer
    model.add(Conv1D(filters=32, kernel_size=3, activation="relu"))
    model.add(GlobalMaxPooling1D()) 
    
    # Dropout layer
    model.add(Dropout(0.3)) 
    
    # Dense (fully connected) layer
    model.add(Dense(classes))
    
    return model
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv1d (Conv1D)             (None, 116, 16)           496       
                                                                 
 max_pooling1d (MaxPooling1  (None, 58, 16)            0         
 D)                                                              
                                                                 
 conv1d_1 (Conv1D)           (None, 56, 32)            1568      
                                                                 
 global_max_pooling1d (Glob  (None, 32)                0         
 alMaxPooling1D)                                                 
                                                                 
 dropout (Dropout)           (None, 32)                0         
                                                                 
 dense (Dense)               (None, 2)                 66        
                                                                 
=================================================================
Total params: 2130 (8.32 KB)
Trainable params: 2130 (8.32 KB)
Non-trainable params: 0 (0.00 Byte)
_________________________________________________________________

Converting the TFLM:

import tensorflow as tf
import pathlib, os 
from tinymlgen import port
modelPath = "Loss_Best_1DCNN_model_120"
  
converter = tf.lite.TFLiteConverter.from_saved_model(modelPath) # path to the SavedModel directory
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float32]
tflite_model = converter.convert()

saved_model_loaded = tf.saved_model.load(modelPath)
# Use tinymlgen to convert the model to C code
c_code = port(saved_model_loaded, optimize=True, pretty_print=True, variable_name="model_p")
open("quant_f32_port.h", "w").write(c_code) 

Here's the list of supported operators: https://github.com/eloquentarduino/tflm_esp32/blob/5fe67df0264113863fa54997924e20b01df31318/src/tensorflow/lite/micro/micro_mutable_op_resolver.h

Conv1D and GlobalMaxPooling1D are not supported. These days, coincidentally, I was thinking of using a Conv2D with shape 1 x N as an hack to emulate Conv1D, you may try that. As for the GlobalMaxPooling, you can replace it with a MaxPooling of the correct shape, I guess.