MbedOs error when reading analog in

Nucleo F446re
Mbed studio

Whenever I try to read an analog value from any of the analog in pins, i get the following error.

++ MbedOS Error Info ++ Error Status: 0x80010133 Code: 307 Module: 1 Error Message: Mutex: 0x20000510, Not allowed in ISR context Location: 0x8009869 Error Value: 0x20000510 Current Thread: rtx_idle Id: 0x20001D90 Entry: 0x8007441 StackSize: 0x280 StackMem: 0x20001E60 SP: 0x2001FEAC For more info, visit: https://mbed.com/s/error?error=0x80010133&tgt=NUCLEO_F446RE -- MbedOS Error Info --

It happens when I press the InteruptIn button which calls a function. Inside that function there are a few lines of code that run perfectly normal but when it reaches the analog read function, it throws the previous error.

Not to paste my whole program, here is main and the called function.

int main()
{
    pwm_L.period(0.02);
    pwm_D.period(0.02);

    timer.start();              //debounce
    button.mode(PullUp);        //Postavljanje moda guba za paljenje/gašenje vozila
    button.rise(&toggle);       //Poziva funkciju koja sve pokreće/zaustavlja*/
}
void toggle()
{
    if(timer.read() > 0.5)  //Unutar ove petlje kako bi smo izbjegli debouncing
    {
        brojac++;

        pokreni_motore();
        timer.reset();

        float desni = ante.read();    //Error here
    }
}


void pokreni_motore()
{
    //ucitaj_podatke();
    if(brojac % 2 == 0)
    {
        pwm_L.write(MAX_BRZINA);
        pwm_D.write(MAX_BRZINA);
    }
    if(brojac % 2 != 0)
    {
        pwm_L.write(0);
        pwm_D.write(0);
    }

}

The analogIn pin is declared as:

AnalogIn ante(A1);  

Anyone know why it would do something like that?
Important thing to note is that when i run thise code, it works without any errors.

#include "mbed.h"
//Slave adresa  0x1E


AnalogIn foto(A5);
DigitalOut led(LED1);



int main()
{
    
    while(true)
    {
        float val = foto.read() * 3300;

        printf("%.2f\n", val);
        ThisThread::sleep_for(100);
    }
}

Hello,

the error tell you what is wrong

MbedOS has most of methods covered by Mutex - printf, read/write, send/received and so on.

In context of your code. Method AnalogIn::read, what you call from ISR context, contains Lock/Unlock and we can found above that is not allowed.

Options:

  1. place just a bool flag into your ISR handler, somewhere in a loop place an if statement with that flag and inside of that just place the AnalogIn::read
  2. use EventQueue and take it out of interrupt contex. You can use first example as a reference and just replace the printf with AnalogIn::read
    For settings click here

    For EventQueue could be necessary this settings in mbed_app.json file

    {
        "target_overrides": {
            "*": {
                "platform.callback-nontrivial": true
            }
        }
    }
    
  3. if you don’t need RTOS functionality, then switch to bare metal profile = no RTOS = no Mutex = no error about mutex
    For settings click here

    For bare metal you have to set content below into mbed_app.json file

    {
        "requires": ["bare-metal"]
    }
    
  4. you can override lock and unlock methods with empty methods because are virtual.
    For example click here

    place it into the main and use it like regular AnalogIn object

    #include "mbed.h"
    
    class MyAnalogIn : public AnalogIn {
    public:
        MyAnalogIn(PinName inp) : AnalogIn(inp) { }
        virtual void lock() { }
        virtual void unlock() { }
    };
    
    MyAnalogIn foto(A5);
    // rest of your code
    

BR, Jan

1 Like

I realized the mistake in my code. I was trying to run everything from the interupt.
I changed the code by making the interrupt only change a bool to true or flase and had the resto of the functions in a while loop in main.

int main()
{
    pwm_L.period(0.02);
    pwm_D.period(0.02);

    timer.start();              //debounce
    button.mode(PullUp);        //Postavljanje moda guba za paljenje/gašenje vozila
    button.rise(&toggle);       //Poziva funkciju koja sve pokreće/zaustavlja

    while(aktivan)
    {
         ucitaj_podatke();

        pokreni_motore();
    }
}

And this is my toggle function

void toggle()
{
    if(timer.read() > 0.25)                         //Unutar ove petlje kako bi smo izbjegli debouncing
    {
        aktivan = !aktivan;

        if(!aktivan)
        {   
            pwm_L.write(0);
            pwm_D.write(0);
        }

        timer.reset();
    }
}

Now Im having problems changing the bool value. When i press the Interrupt button, this function runs but the aktivan value changes from false to “unknown” acording to the debugger. And as such the while loop iN main doesnt run but when I change aktivan to true from the start it runs normally.

All I want to do is use Interrupt to change a bool value back and forth, is that possible or am I missing something and you cant use Interrupts like that?

Of course, because it doesn’t make sense.

  • your variable aktivan should be declared as volatile bool, that will prevent compilator optimization to a constant value.
  • you can not use the flag like that, because as soon as your flag will be false, then the program end. This loop must be true forever.

as a reference you can use button examples from my old posts

Let me know if you have future question

BR, Jan

1 Like

Got it working, really appriciate your help.
Im coming from a windows C++ background where I had the luxury of virtually unlimited resources and a compiler with zero intrusive opitimizations which compiled everything I threw at it. So as you can imagine, this transition has been challenging.