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

How to use setjmp and longjmp to simuate watchdog timer for FX2 chip?

Hi,

Since FX2 does not have a watchdog timer, I am trying to simulate watchdog behavior using Timer 2 on chip.

The timer setup seems to be functional, but when I try to execute longjmp(), FX2 dies. Any future access to the chip will hang. In the debugger, when I try to execute longjmp(), I will loose the debug connection. Thee only way to get it back is to reset USB.

Is this because of longjmp() or some other thing that I don't know. If it is not appropriate to use longjmp, how can I simulate the watchdog behavior so that lockup in 8051 can be prevented.

Any comments are welcome,

Thanks,

zhongsheng

here is the pseudo code I am using:

void main()
{ // ReEnumeration setjmp(jmp_buf); // Hardware setup // Initialization while (1) { // interrupt handling }
}

void ISR_Timer2 interrupt 5
{ TR2 = 0; TF2 = 0; longjmp(jmp_buf, 3);
}

Parents Reply Children
  • Thanks for comments from all of you. All comments are very important to me.

    I am using FX2, therefore, there is no alternative for external chip reset besides USB bus device. However, if the device is self-powered, USB bus reset has no effect on the chip.

    The reason I said "software reset is what I am looking for" it that I don't know how to get out of interrupt service routine before. The software reset thread explains that. The concerns about CPU state and hardware status can be avoided using setjmp/longjmp and hardware initialization (I think). A diag after hardware initialization is necessary to make sure that the hardware is actually working. If diag failed, the diag status will be reported to the host. The host should be able to decide what to do next.

    Here is what I have implemented. It seems to work for me in my hardware environment.

    void main()
    { ... // ReEnumeration

    if(setjmp(T_JmpBuffer)) { soft_reset(); // get out of watchdog interrupt }

    ... // Global variable initialization ... // Hardware initialization ... // Hardware diagnostics while (1) { // report execution status }
    }

    void OnWatchDogTimerInterrupt() interrupt TMR2_VECT
    { ... // stop watchdog timer ... // clear watchdog timer interrupt status

    ... // Report the watchdog timer event

    soft_reset(); // get out of ISR_SUDAV

    longjmp(T_JmpBuffer, 3);
    }

    void ISR_SUDAV(void) interrupt 0
    { .... StartWatchDogTimer(); OnVendorCommand(); StopWatchDogTimer();
    }

    PUBLIC reset_again
    reset_again: RETI ; execute return of interrupt END

  • Don't bother with setjmp/longjmp. Just do what the processor does, and start executing at address 0 by casting 0 to a pointer to a void/void function:

    typedef void (CODE* Vector) (void);

    (*((Vector)0))();

    Previous posters have explained why this is not equivalent to resetting the processor. Any processor state (SFRs, interrupts, etc) do not return to their initial value. And, in fact, if you leave interrupts enabled while you "reset", you might get some strange results. So you may well find yourself adding more and more code to get the software reset to look more like a hardware reset.

    How about connecting a GPIO pin to a reset in the power supply? You could connect it to the reset pin of the chip, but that gives you possible problems with the stablity of the GPIO when coming out of reset. So you often need some external hardware make make the reset stable. And, as long as you're resetting, it's often useful to have a board-level power-on reset to make sure everything on the board gets reset, not just the processor.

  • if you have the reset request inside an ISR, you have, (for most derivatives) a bit set in a register inaccessible to you that will blow your restart.

    A known method to reset this bit is to patch the stack with 00 00 and execute a RETI instead of just JMP 0.

    Again the so called 'soft reset', is real FUN you will learn all kinds of stuff.

    The RIGHT way would be to add a supervisor with watchdog such as the 1232

    Erik

  • "The RIGHT way would be to ..."

    Up to the old tricks again!?

    Why not giving something other than the Erik-is-right-because-Erik-writes-it style response. Huh ???

    It's like saying the right way to make tea is to put the milk in the cup after the tea.

    It implies that any other way is wrong.

    Of course, everyone knows that the real RIGHT way to make tea is to add the tea to the milk ;)

  • IMHO the RIGHT way is to forget ALL abiut the udderly stupid idea of "political correctness". If someone need their answers wrapped in pink cotton, they are welcome to skip my posts.

    Erik

    PS I know how to spell 'utterly' but political correctness is a bovine idea.

  • "...wrapped in pink cotton..."

    Erik,

    I've seen you mention this phrase a number of times now.

    Is it an indication of some strange unconscious desire or fetish?

    I'll have to consult my collection of Sigmund Freud publications to see whether it explains your egotistical posts.

  • I have tested my implementation. It seems to be working in terms of continuing execution after longjmp().

    However, I have found two more problems:

    1. the code works if there is no debugger. If I have Keil monitor loaded and run the code within Keil Debugger, the debug connection may get lost.

    2. The watchdog timer interrupt has high priority. Its nature priority (6) is also higher than USBINT (8). However, the high priority ISR does not pre-empt the lower ISR in this case. When I try to simulate a timeout situation by holding the peripheral device in stop mode while USBINT ISR is trying to access the peripheral device, the watchdog timer interrupt ISR will not run after timeout period (4 sec). The watchdog timer ISR will run when I let the peripheral device to go.

    Any comments on that?

    Thanks,

    zhongsheng

  • 1) the IE priority which allow an interrupt to interrupt another.
    2) the "simultaneous event priority", I qoute "the bible" (my emphasis)
    If requests of the same [IE} priority level are received simultaneously, an internal polling sequence determines which request is serviced. Thus within each priority level there is a second priority structure determined by the polling sequence.

    Erik

  • I think I know what you are saying.

    WatchDog Timer interrupt (Timer 2, 0x002B):
    Assigned Priority: High
    Nature Priority: 6

    USB Interrupt (0x0043):
    Assigned Priority: Low
    Nature Priority: 8

    Apparently, Timer 2 interrupt has higher priority than USB interrupt in both assigned and nature priority level. However, I just don't understand why Timer 2 ISR was not invoked when Timer out condition has been reached. I assume Timer 2 count should continue even the firmware is hung.

    Thanks,

    zhongsheng

  • is that they can be turned off by simple means.

    In my opinion no watchdog that can be turned off by simple means qualify as a watchdog, simply because runaway code easily can effect the turnoff.

    Erik

    turned off by simple means: e.g. clearing a bit or byte - in your case e.g. IE or EA or ET2.
    turned off and still be a watchdog: e.g. a requirement if two specific consequtive writes.