Is there a way to return from interrupts at a different location from where the interrupt occurred in Microchip PIC16F877A?

I have a problem where I need my code restarts at a specific point always an external interrupt occurs and the ISR is just finished.

I'm thinking in use in-line assembly instructions in my C code to get the address I want to return and to change the top of stack to that address, but I guess the PIC16F877A doesn't support that.

  • \$\begingroup\$ Why not have the next instruction after the ISR send you where you want to go? \$\endgroup\$ – EM Fields Oct 11 '14 at 23:23
  • 1
    \$\begingroup\$ Because I don't know what is the next instruction after the ISR. It depends on where the Program Counter was at the moment of the interrupt. \$\endgroup\$ – user49894 Oct 11 '14 at 23:45
  • 1
    \$\begingroup\$ Unfortunately the PIC16 series doesn't give you access to the stack registers, so there's no way for you to manipulate the return address. If you really need this functionality, you'll have to upgrade to a PIC18. \$\endgroup\$ – brhans Oct 12 '14 at 1:35
  • 3
    \$\begingroup\$ What, exactly are you trying to do? \$\endgroup\$ – gbulmer Oct 12 '14 at 1:41
  • 1
    \$\begingroup\$ You can't do what you ask for on that PIC, but this sounds like a implementation detail you have imagined instead of your true problem. It also sounds like kludgy software architecture if you want to do this. \$\endgroup\$ – Olin Lathrop Oct 12 '14 at 13:38

You are correct, PICs before PIC18 didn't give a way to change the top of the stack.

You are asking one of the classic questions which has caused me to avoid PIC's, and especially everything pre-PIC18 like the proverbial plague. wikipedia PIC stack

It is a perfectly normal thing to do, providing you understand what you are doing, and not illogical. It is a core mechanism for multi-tasking, or muti-process operating systems.

The normal reason for doing something like that is to do an operating system (OS) context switch. This would enable software to create the illusion of many concurrent processes. When an interrupt has been serviced, the OS might not want to return to the interrupted process, but may need to run a different piece of code. Part of the mechanism is to change the stack pointer to the stack of a different process, and then execute the return from interrupt.

See AN818 Manipulating the Stack of the PIC18 Microcontroller for how to change the return address. Note it is a PIC18 document.

Sadly AFAICT that PIC is not capable of doing that.

An inferior alternative technique is to have your main control loop check a variable to detect when it needs to get out, and execute that other code.

Is there a way to force a RESET?

  • \$\begingroup\$ Hi, gbulmer! I was trying to find a way of change the top of stack exactly to avoid that inferior alternative you mentioned. But if there is no way of manipulate the stack, I will have no choice. \$\endgroup\$ – user49894 Oct 12 '14 at 13:01
  • \$\begingroup\$ @stdio.h - I strongly sympathise. It is a perfectly reasonable thing to want to do. Many years ago, a chum of mine wrote something like the core task-switching for a real-time OS in C++, with only, about, 4 lines of assembler to manipulate the stack pointer, and do that stack swap. It was just a library, that ran inside an ordinary process. I assume there is no way to upgrade the MCU? \$\endgroup\$ – gbulmer Oct 12 '14 at 13:37
  • \$\begingroup\$ It's an undergraduate assignment. I guess my teacher will tell me is better to write an inferior code than upgrade the MCU at real life situations. But I'm really prone to upgrade the MCU, because I hate checking of flags in all my code. It looks like a quick fix. \$\endgroup\$ – user49894 Oct 12 '14 at 14:27

No, what you are asking for is both impossible and illogical.

It'd be like changing lanes on a freeway then changing back to the first lane but wanting to be 25 miles away travelling in the other direction. It just isn't going to happen unless you change the laws of physics, or create a wormhole, and trust me, you don't want to do that.

An interrupt is exactly what it sounds like - it interrupts the normal flow of the program to perform some operations, then the normal flow of the program resumes. The interrupt has no direct control over that program flow - all it can do is modify variables that your main program could examine to see if a restart is required.

Another analogy would be you're working at your desk writing a letter. The phone rings and interrupts you. You answer it. When you put the phone down you are still at your desk with your letter in front of you. Putting the phone down can't teleport you to the toilet.

For more clarification, a quick perusal of the datasheet provides all proof you need to know it's impossible:

The PIC16F87XA family has an 8-level deep x 13-bit wide hardware stack. The stack space is not part of either program or data space and the stack pointer is not readable or writable. The PC is PUSHed onto the stack when a CALL instruction is executed, or an interrupt causes a branch. The stack is POP’ed in the event of a RETURN, RETLW or a RETFIE instruction execution. PCLATH is not affected by a PUSH or POP operation.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy