Esp32 detect if noInterrupts() call has been made? <SOLVED>

Use case is a logging function, which outputs directly to serial but might output a lot. In the case of an atomic noInterrupts(); ... interrupts(); block this blows up because it can't flush the port.

I solve this by buffering the output internally and then flushing at the top of the loop() but this can cause the logs to appear out of order. Not a huge deal since I am aware of it, but I'd like it to be cleaner.

I'd like the log function itself to detect if interrupts (global) are enabled and buffer if so*

Is there such a function? I can't seem to find one in the docs.

*idea is: each log function checks the flag, if it's NOT set and there is buffered data, it outputs that data, then whatever log it was told to. That way the logs stay in order. At the top of loop() or wherever It will also flush, in case no logs are made after the buffered one.

First, explain how your code can be attempting serial I/O with the interrupts off. It is an exceedingly bad idea. I suspect that you misunderstand some basic concept.

Always post the code, using code tags.

First, explain how your code can be attempting serial I/O with the interrupts off.

Yes, that is the point. I want to buffer the output and push it out of the serial port after the ISR has ended... code? ok..

noInterrupts();
Serial.println("don't do this");
interrupts();

char buffer[64];
noInterrupts();
sprintf( buffer, "do this instead" );
interrupts();
Serial.println( buffer );

What I'm looking for is:

log( const char* someLog )
{
    if( interrupsAreDisabled() )
    {
        // buffer it
    }
    else
    {
        // log it
    }
}

So I don't have to code it case-by-case.

If you didn't write the code, go through it and correct all those beginner mistakes. Or start over, with code that was correctly written from the outset.

wow ouch. Any serious answers?

Are you serious about your project?

If so, don't start with someone else's junk. There are undoubtedly other terrible mistakes.

@tinker_curt interrupts should only ever be disabled for absolute minimum of time. For example just enough time to read a variable that gets updated by an interrupt, and then interrupts should be immediately enabled again.

The longer interrupts are disabled, the higher the probability that interrupt events will be completely missed.

If your code is disabling interrupts for longer periods, certainly the time it takes to write something to serial, that's not a good design at all.

To answer your question directly, I don't think there is any function to check if interrupts are disabled. You could set a global flag in your code when you disable or enable interrupts, and check that flag. But I wouldn't advise it. I think you need to re-engineer your code so that it's never needed.

Thank you for your response. I only disable interrupts for a bare minimum of time as a poor-man's atomic lock to pop entries off a LL (it's pulling packets off a CAN bus to be consumed in the main loop)

Trouble is I might need to log a lot of info based on that entry, the real solution is to implement a proper semaphore/lock for that list and then this isn't an issue. Should not have been lazy to begin with :slight_smile:

-Curt

Pass a bool flag to your logging function indicating interrupt condition. The calling function will set it accordingly.

Thank you for an excellent suggestion! I considered this, and it does solve the problem neatly, but the fact is this case comes up very rarely and I don't want to have to add a "false" everywhere but the few places it matters.

See above, I'll just properly protect access to the contended resource and then the issue goes away.

Incorrect code design, if it interferes with unrelated processes.

That's easy enough, just use a default parameter in your function prototype:

void logSomething( const char* someLog, bool interruptsOff = false );

Then you only have to supply the second argument if it needs to be true.

Excellent suggestion, unfortunately my log function uses varargs so this would not be possible, it would need to look like

void log( const int level, const bool interruptsOff, const char* format, ... );

I should have been clearer in my previous response.

I could overload the log() function though, or even be explicit and add logISR() or some such.

But this is cure worse than disease. This is really just being lazy, I'll critical-section-ify the relevant list and do it right.

I wouldn't call it log for fear of it getting balled up up with the mathematical of the same name.

Excellent point, I remember many years ago running across that very problem. These are simplified code examples for clarity. In the code it's out(...) and outln(...) and when that fails me I often use emit(...)