This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Jumping to function after timer interrupt

In my program, I have a periodic timer interrupt written in C.

What I need to achieve is to have the interrupt service routine jump to another function after the interrupt service routine is executed.

However, the catch is that the address of the function (which the program is suppose to jump) is stored as a variable (which is not fixed each time the interrupt occurs).

Im looking for advice on how can this possibly be done. Thank you.

Parents
  • More specifically, what I need to do is for this particular function is be called once the interrupt routine has been executed. It would have to be different from the usual behaviour of an interrupt where the interrupted program will resume.

    I understand that I can use a function pointer to call the function from the interrupt routine. But unfortuntately, this function concerned has a infinite loop which loops forever. For example,

    void loop_function (void){
    for (;;) {}
    }

    As such, I cannot simply call the function from the interrupt routine. This is because the program will be stuck in the infinite loop. Hence, the next periodic timer interrupt would not set in as the previous interrupt is considered to be still running.

    Could what I want possibly be achieved in C? Or do I have to go into assembly?

Reply
  • More specifically, what I need to do is for this particular function is be called once the interrupt routine has been executed. It would have to be different from the usual behaviour of an interrupt where the interrupted program will resume.

    I understand that I can use a function pointer to call the function from the interrupt routine. But unfortuntately, this function concerned has a infinite loop which loops forever. For example,

    void loop_function (void){
    for (;;) {}
    }

    As such, I cannot simply call the function from the interrupt routine. This is because the program will be stuck in the infinite loop. Hence, the next periodic timer interrupt would not set in as the previous interrupt is considered to be still running.

    Could what I want possibly be achieved in C? Or do I have to go into assembly?

Children
  • If you were to explain why you are trying to do this it might be easier to help.

    So far it looks as though you don't ever want execution to return to the 'main' program after this interrupt handler has been executed, you want your endless loop function to run, however you want all ISRs to continue executing in response to interrupts.

    This sounds quite strange - perhaps you could design your program differently?

    Stefan

  • "But unfortuntately, this function concerned has a infinite loop"

    Why?!

    "I cannot simply call the function from the interrupt routine. This is because the program will be stuck in the infinite loop."

    Of course it will - that's the nature of infinite loops! That's why they're called "infinite!"

    It sounds like your design is fundamentally flawed: if you have these infinite loops, then you will get stuck in them - no matter how you get into them!

    I think you probably don't want infinite loops at all; I suspect what you really want is loops that run until the next timer event, or something like that?

  • Yes you are right. The program would not return to 'main'. Instead it will jump from function to function.

    The purpose of doing this is to create an application which can run different tasks (functions) in a round robin fashion. These tasks can execute forever until they are pre-empted by another task when the timer interrupt sets in.

    What I describe may sound a bit pointless but it is actually part of an overall effort to build a context switching routine for a very basic real-time OS in 8051.

  • Hi
    Try this code

    #include    <REG51.h>
    
    char idata *STACKPointer;
    char data Low_adr;
    char data High_adr;
    
    //Replace this function to our Interrupt function
    void Init8051(void)
    {
    
    STACKPointer = (char *)SP; //Get Stack
    STACKPointer--; 			//Remove calling function
    STACKPointer--;
    
    //Return to new function
    STACKPointer[0]=High_adr;
    STACKPointer[1]=Low_adr;
    }
    

  • The purpose of doing this is to create an application which can run different tasks (functions) in a round robin fashion. These tasks can execute forever until they are pre-empted by another task when the timer interrupt sets in.

    To make a preemptive multi-tasker on an 8051, I don't think you'll get by with writing everything in C. You'll have to code at least some of the core pieces in assembly. You'll have to manipulate the stack on each context switch triggered by the timer interrupt.

    I would strongly suggest to re-evaluate that plan. Preemptive multitasking is hard to do on an 8051, and harder still if you want to stick with C as the implementation language. Cooperative multitasking may very well be a better choice.

  • A simple assembly call can do the task switching for you.

    Switch2TaskII:
        mov Temp, R0
        mov R0, SP
        mov A, @R0
        xch A, ReturnAddressHigh
        mov @R0, A
        dec R0
        mov A, @R0
        xch A, ReturnAddressLow
        mov @R0, A
        mov R0, Temp
        ret
    

  • If you want to switch from task to task, just swapping the program counter is not enough: you will have to save the 'old' environment (stack and registers of the function you are coming from) and restore the 'new' environment (stack and registers of the function you will switch in) at every function jump.
    If you don't have enough experience yet, I suggest you to begin with Keil RTX51-Tiny operating system, it works and it is already included within the PK51 Development Environment.
    Moreover, it is not just a LIB file, source code is there too, so you can study it, understand it and maybe modify it to suit your needs.
    You can run a Keil RTX example into the simulator to understand how the context switch is realized; Keil uses a stack swapping method to maximize the 8051 IDATA memory usage, if you are an RTOS beginner it will teach you a lot!
    Another good source for RTOS learning is the Labrosse book, take a look at

    http://www.ucos-ii.com/

    In the Bookstore Menu you will find the MicroC/OS-II Book; uC/OS-II is a full featured RTOS, written in C, but if you want something 'lightweight' I still suggest you Keil RTX51Tiny.

  • Note that "stack", in the context of overlaid memory, is not just the stack pointer. It's the state of all the overlaid memory as well.

    That is, if you arbitrarily preempt a task at any point in its execution, you can't overlay its memory with that of any other task. Each task will need to be the root of its own call tree.

    Unless you have very few and very simple tasks, the increase in memory consumption will likely mean that you need to use xdata instead of data, and that in and of itself will significantly increase the code side required.

    You'll also need more care to be sure your shared library routines are reentrant, or provide mutual exclusion around them.

    The 8051 architecture, IMO, just isn't well suited to preemption.

  • The 8051 architecture, IMO, just isn't well suited to preemption.
    Amen.

    Erik

  • From the Philips forum:

    Wilson Teo

    Post subject: 89C51RD2 and SDCC

    Pardon me for my ignorance as I am very new to 8051 and SDCC. Thank you in advance.

    Wilson: As stated above, multitasking and the '51 do not make a good match, WHY are you trying to do this?

    Erik

  • Hi

    I guess it might not make sense to a lot people why I am doing this.

    Anyway, this is actually part of my academic project where I am suppose to port an existing small footprint RTOS from the x86 to 8051.

    Would appreciate anyone who can explain further why it is unsuitable though it might be achievable?

  • Would appreciate anyone who can explain further why it is unsuitable though it might be achievable?
    Since you are obviously allergic to reading up on the '51 architecture, that would be tough. So let me make it simple read the 3 chapters of "the bible" referred to and concentrate on the references to "memory types" and stack.

    Erik

  • Hi Erik

    I have actually read up on the '51 architecture. Please pardon me for my ignorance if I was not able to understand the whole picture and hope to seek some advice from the more experienced.

    Anyway, I had create a context switching routine for pre-emption of tasks in my application. It is working fine but I would appreciate any more opinions on the idea of implementing pre-emptive multitasking on the '51.

    Thank you.

  • It is working fine but I would appreciate any more opinions on the idea of implementing pre-emptive multitasking on the '51.
    Let me give you "opinions on not implementing PEM (pre-emptive multitasking) on the '51."

    1) The '51 is a microcontroller and microcontrollers are not made for number crunching, but for rapid response to external events. This ability, which is the only one i know for selecting a microcontroller over a microprocessor will be totally lost if PEM is implemented.

    2) If more than one task is to be performed, the correct way to do so with microcontrollers is to make a "uC farm" e.g. one processor handling operator I/O, another handling the actual process and a third communication with the outside world.
    In such a scenario you could use say 3 LPC932 chips at $1 each, so why screw around with killing the performance in order to use a $10 processor instead of 3 $1 processors.

    If you want to implement PEM, do it on a processor suited for it. You take your car, not your riding lawnmower when you go to the grocery store I presume.

    Erik