arduino / ArduinoCore-nRF528x-mbedos

[Archived] Arduino core supporting mbed-enabled boards
86 stars 34 forks source link

AnalogRead() runtime error in Ticker ISR function #89

Closed fgaetani closed 4 years ago

fgaetani commented 4 years ago

I tried to use tickers because in my code I have a critical part that must be performed every 10ms, however I noticed that in tickers ISR functions I cannot run analogRead(). When i do it the microcontroller goes into runtime error (led blink). Is there any way to see what kind of runtime error it is? Is there a solution or alternative to tickers at this problem? I have the same bug with mbedOS 5 and mbedOS 6.

Thanks for the support!

You can reply verify this issue with this simply code:



mbed::Ticker flipper;
bool a=false;
int val = 0;

void flip(){
    if(!a){
      digitalWrite(LEDR, HIGH);
      a = true;
    }  
    else{
      digitalWrite(LEDR, LOW);
      a = false;
    }
    val = analogRead(A0);   
}

void setup() {
    flipper.attach(&flip, 0.01);
    Serial.begin(115200);
}
void loop() {
    Serial.println("While");
}
facchinm commented 4 years ago

Hi @fgaetani , the error is due to calling a Mutex lock inside an ISR. While not directly visible, the function we wrap when reading an analog voltage does this to prevent concurrent reads https://github.com/ARMmbed/mbed-os/blob/ffeb926a673c979047e98b888b44c62450f2d0f2/drivers/source/AnalogIn.cpp#L49-L55

We should definitely add this to the documentation; to discover where the hang is happening you can connect a serial-to-usb cable to pin TX1 with the serial port configured as 115200@8n1 ; you will get something like

++ MbedOS Error Info ++
Error Status: 0x80010133 Code: 307 Module: 1
Error Message: Mutex: 0x200020EC, Not allowed in ISR context
Location: 0x16D07
Error Value: 0x200020EC
Current Thread: main Id: 0x2000A5FC Entry: 0x16C33 StackSize: 0x8000 StackMem: 0x200025D8 SP: 0x2003FED4 
For more info, visit: https://mbed.com/s/error?error=0x80010133&tgt=ARDUINO_NANO33BLE
-- MbedOS Error Info --
fgaetani commented 4 years ago

Hi @facchinm,

Isn't there any way to perform an analogRead with a fix timing that does not depend on the execution of the loop?

Thanks!

facchinm commented 4 years ago

mbed-events could be helpful since you can enqueue the analogRead with queue.event(&do_something) when the Ticker fires, and the actual read will be performed in the event thread (not in interrupt context)