call from within ISR

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Freaks, maybe someone could help me. I'm calling a function from an ISR but it fails when called from within an ISR. Otherwise it functions corrrectly.

ISR Code

void compare_irq_handler(void)
{
	extern void os_load_task();
	compare_isr_fired = true;
	Set_sys_compare(NB_CLOCK_CYCLE_DELAY_LONG);
	os_load_task();
	}

Function Call

void os_load_task(void){
	asm("MOV     R12, LO(OSTCBHighRdy)");
	asm("ORH     R12, HI(OSTCBHighRdy)");
	asm("LD.W    R10, R12[0]");
        asm("LD.W    R12, R10[0]");
	asm("LDM     R12, R0-R7");
	asm("LD.D    R8,  R12[14*4]");
        ....
        ....

It would appear that the variable OSTCBHighRdy is not correct, its defined has a global volatile variable.

Any help is much appreciated.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess that function is not reentrant.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, so how should I proceed to correct this. Your help is much appreciated.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For a non-reentrant function (if that is the case) you need some way to block multiple instances of the function running simultaneously.

One way to do this could be something roughly like this: Implement a flag that signals that the function is running. Upon every attemt to start the function the flag is inspected and the function is only allowed to run if the flag is false. The very first thing the function does is set the flag, and the very last thing it does is to clear it. You will also need to make sure that from the moment before inspection of the flag to the moment after the setting of it, NOTHING comes in between. Thus, this section needs to run with interrupts disabled.

Implementing something like this is not trivial, and is not easily debugged.

I would advice to restructure your code so that reentrancy does not come into play. This will likely involve never calling the funxtion from the ISR, but rather let the IST flag the event in some global variable, and let "the main path of execution" inspect that variable and call the function.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Its not possible to implement such a programming structure. I also however do not think it is a re-enterant issue. Basically the function works when called elsewhere but when called from within the ISR it fails.

To add a littl more insight to th problem the function being called performs a context switch... Maybe this will help you help me.

Thanks for your time, it is very much appreciated.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Its not possible to implement such a programming structure.

I simply do not believe you. It might be a major effort - but not impossible.

Quote:

I also however do not think it is a re-enterant issue. Basically the function works when called elsewhere but when called from within the ISR it fails.

Combined with the already stated fact that this function accesses a global variable this sounds as either a reentrancy issue, or simply the variable not being declared volatile.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
To add a littl more insight to th problem the function being called performs a context switch... Maybe this will help you help me.
If a context switch is performed, the stack changes as well, doesn’t it? This means that a different set of previously stored system registers get popped from the new stack. Restoring system registers that were stored in application mode in privileged mode and vice versa sounds like a Bad Thing. Actually, performing a context switch in application mode is a Bad Thing all in itself. (Well, unless you use user threads, but those would never be changed in privileged mode.)

It sounds like your task management is inherently flawed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks for the suggestions. I'll investigate these recommendations...

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

catweax

I think your on the right track has to why I'm experiencing errors. I create the context in main and then try and load it in the interupt routine.

so how do I achieve this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, no idea. Haven’t used anything like that myself yet.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, thanks for the suggestion...

Slán

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fianawarrior wrote:
catweax

I think your on the right track has to why I'm experiencing errors. I create the context in main and then try and load it in the interupt routine.

so how do I achieve this?

I've done exactly this on a Freescale processor (9S12) and I had to set up the context from within interrupt context. It may or may not be your problem, but it would be worth a shot. Instead of setting up the context in "main", set it up in a one-time interrupt you generate from a timer or something. On the 9S12 I used a software interrupt, but I'm not sure the Atmel processor you are using has an SWI. So basically, set up a timer interrupt in main, then just loop until your timer interrupt gets called. When it gets called, set up the context within the timer interrupt, then when it completes continue on in "main". Then switch to that context within the interrupt you are already using.

HTH.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Klausb, I was thinking the exact same thing. But I think I've found the problem. It appears that when the task is created in main then its supervisor mode is different than in an interupt. Thus the error. Your method will work. But so to does setting the status mode flags in the interupt.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Klausb, you and I where correct. At it simplist, when returning from an interupt you must use RETE and not RETS.

Problem sorted, now I my get on with my life.