Interrupt like environment within normal code

Just wanted to check if my logic is correct here. I’ve a section of code which can be run by an interrupt routine, but which I also need to be able to run from a trigger within the main code. I’ve copied the function code from inside my ISR function in to a second function with a different name.
So I have

void function stuff_isr(){
//code here
}

to ensure that when the same “//code here” gets called from the main function it is in the same global “enviornment” as when it is caleld during an interrupt is the following sufficient

void function stuff_isr_non_interrupt(){
uint8_t oldSREG = SREG;
cli();
//code here
SREG=oldSREG;
}

or is there anything else which has to be done before and after “//code here” so that when “//code here” runs it can’t tell the difference between whether it is being called as an isr with stuff_isr() or from the main code with stuff_isr_non_interrupt().

Thanks

You know, when a question is not common and it feels out of the ordinary, then I start to think about the XY-problem.

Can you tell what the project is for and can you show the full sketch, or at least the code that needs to be executed in the ISR.
Why do you want that code to run from the loop() ? Perhaps you are trying to fix something that was not a problem in the first place.

There are a few ways to write code:

  1. Write code for the code, because those things needs to be done.
  2. Look at the data streams that flows through the code. Buttons and sensors create streams of data and the output stream can be a display.

If your interrupt creates a data stream, then you might disturb the flow of the data by calling it from the loop().

1 Like

A typical way to deal with such things is to simply set a flag in your ISR. The code in your loop() can also set that flag (make sure it is declared volatile) and then, inside loop(), check the flag and execute the code and reset the flag

volatile byte flag;

void ISR() {
  flag = 1;
}
void loop() {
  if ( someSensorFunction() == true ) {
    flag = 1;
  }
  ...
  if ( flag ) {
    // whatever code needs to execute
    flag = 0;
  }
}

My specific situation is I have an interrupt qhich works nicleay, but if it gets triggered during certain other times it needs to not run at that exact moment and it’s contents, the “//code here” stuff need to be able to happen later on from the main code. My overall situation is like

volatile uint8_t NotRightNow=0;
volatile uint8_t MustDoLater=0;

void function stuff_isr(){
if(NotRightNow==0){
//code here
MustDoLater=0;
}else{
MustDoLater=1;
}
}

void function stuff_isr_non_interrupt(){
uint8_t oldSREG = SREG;
cli();

//code here

MustDoLater=0;
SREG=oldSREG;
}

void setup() {
//things
attachInterrupt(digitalPinToInterrupt(2), stuff_isr(), FALLING);
}
void loop(){
//some stuff
NotRightNow=1;
//things where interrupt shouldn’t run
NotRightNow=0;
if(MustDoLater==1){
stuff_isr_non_interrupt();
}
}

My things where the interrupt should not run are not adversely affected by the time that the interrupt takes, hence I don’t wish to use cli() near to “//things where interrupt shouldn’t run” to actually disable interrupts there. But as this code shows I do want to ensure that the “//code here” stuff occurs in the interrupt unless the interrupt fires when “//things where interrupt shouldn’t run” are ongoing, in which case I want to run the “//code here” stuff later. I know that the “// code here” works very well when running as an interrupt, I just want to ensure that there’s nothing else I need add to the stuff_isr_non_interrupt() function to ensure that the “//code here” still behaves as if it was running from an interrupt when it gets called in the “do it later” scenario.

I just need to confirm if the SREG and cli() lines are enough to ensure that “//code here” runs exactly the same when called in an interrupt as when caleld outside one.

Thanks

EDIT: blh64, thanks, you’ve just posted something similar to my aituation. The difference is that I’m adapting some earlier code of mine here. In the earlier code version “//code here” only ever happened within an interrupt and features some things which might work differently if done outside of the “environment” you have during an interrupt. I’m trying to check whether the SREg and cli() lines are enough to fully replicate the “in an interrupt” environment for the duration of the //codehere" part.
Thanks

Take @blh64’s code one small step further by putting the “// whatever code” into a function.

Then the function gets called if the ISR sets the flag, and it can be either called directly by you at the high level or you could even just set the same flag yourself anywhere and the function would be called by the same thing that notices the flag.

volatile byte flag;

void ISR() {
  flag = 1;  // set flag so magicBus gets called eventually
}

void loop() {
  if ( someSensorFunction() == true ) {
    flag = 1;
  }
  ...
  if ( flag ) {
    magicBus();
    flag = 0;
  }
  ...
  magicBus(); // call it yourself or
  ...
  if (whatever)
    flag = 1;  // set the flag so the function runs up where the flag is checkered
}

void magicBus()
{
   // whatever code needs to execute
}

I think you could call magicBus() directly from within interrupt. If you have time to do that and must eliminate the indeterminacy of the delay until the flag is noticed.

HTH

a7

That solution is non-ideal. Suppose “someSensorFunction()” or “(whatever)” causes flag = 1. Then the ‘if’ statement evaluates to true:

  if ( flag ) {
    magicBus();
    flag = 0;
  }

But, what if interrupt occurs while body of ‘if’ statement is executing:

  if ( flag ) {
    magicBus();
                        <-------- Interrupt occurs here and sets flag = 1
    flag = 0;           <-------- flag set to 0. 
  }

So, next time through loop(), the call to magicBus() that should take place due to interrupt won’t happen.

Guess it depends how critical that is to your application.

11 posts were split to a new topic: The trouble with assumptions

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.