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

ASM+C51

Hi everybody

How can I restart the controller by internal rautine?(To simulate the external restart button)

  • About the closest you can get to this is:

    1) Set all SFRs to their default values
    2) Jump to the reset vector

    If your derivative has a watchdog let it time out instead of doing the above.

    Stefan

  • I second the nomination for the watchdog timeout, if you have it.

    Depending on your hardware, you perhaps could wire a GPIO pin to the reset switch to allow the software to reset itself.

  • An alternative method is to jump at the reset location (called warm boot).

    for example if your reset vector is located at 0x0000, you can use this C statement

    (*((const void(code*)(void)) 0x0000 ))();

    (equivalent with LCALL 0 )

  • "An alternative method is to jump at the reset location"

    Alternative to what? Did you actually read the thread?

    "(*((const void(code*)(void)) 0x0000 ))();"

    You've gone a bit over the top with the asterisks. Try:

    ((void(code *)(void))0x0000)();

    Stefan

  • "Did you actually read the thread?"

    Obviously not - as he missed the bit about restoring all SRFs to their default values.

  • Dear Stefan

    Both statements are corect.
    Both make a warm boot.
    But there is a DIFERENCE:

    Our statements are translated diferent :

    ((void(code *)(void))func_adr)(); 		--->LCALL 00H
    
    (*((const void(code*)(void)) 0x0000 ))();	--->LJMP 00H
    

    See the diference??
    I think, the LJMP is preferable to the LCALL when a warm boot is nedeed.

    PS:
    in my previous post i made two mistakes:
    1)
    I misplaced the "is" word
    the text:
    "An alternative method is to jump at the reset location (called warm boot)."
    must be replaced with
    "An alternative method is to jump at the reset location (called warm boot) is:"
    Sorry.
    2)
    the text:
    (equivalent with LCALL 0 )
    must be changed with:
    (equivalent with LJMP 0 )
    Those "pointer to function" stuff, can be very tricky, indeed.

  • "Our statements are translated diferent"

    Not when I compile them:

    46: (*((const void(code*)(void)) 0x0000 ))();
    000050 120000 LCALL 00H
    47:
    48: ((void (code *)(void)) 0) ();
    000053 120000 LCALL 00H

    Stefan

  • Hi everybody.

    Thank you all for your answers.

    I am using DK3200. I am using your advices during external interrupt.
    The problem is that the CPU is stucked after the reset function.(the reset function is the last function in the interrupt routine).
    I need the reset as the last function in the interrupt routine.
    In addition I don't want to waste another pin for hardware reset.

    Thank you all Kobi

  • .... I forgot some thing.

    I think that the writing to the LCD is the source of the problem.(but I need it)

    I am adding the code

    void lid_int (void) interrupt 0 using 3	// LID Interrupt
    {
      unsigned char *chr_ptr;
    
      EX0 &= 0x00;//Disable external 0 interrupt
      IE0 &= 0;     // Clear INT0 flag
    
      P1_2 = 0;    // Disable relay
      PWM_Duty_Cyl(0,255);
      PWM_Duty_Cyl(1,255);
      uPSD_PWM_Disable();
      P3_1 = 0;        // Disable BL motor
      P3_0 = 0;        // Disable turbine motor
      P1_1 = 0;        // disable sensors
    
    
      lcd_clear();
      chr_ptr = "THE LID IS OPEN!\n";
    
      while (*chr_ptr != NULL)
      {
         if (*chr_ptr == '\n')
         {
     	    chr_ptr++;
      	    Cursor_LCD ^= 0x40;     			//goto next line
      	    Cursor_LCD &= 0xC0;     			//return to position 0
    	    LCD_reg.LCD_CMD_WR = Cursor_LCD;
         }
         else
         {
            BusyCheck();
            LCD_reg.LCD_RAM_WR = *chr_ptr++;
         }
      }
      while(P3_2 == 0) // Until the LID is open
      {
    
      }
    
      (*((const void(code*)(void)) 0x0000 ))();
    }
    

    Thanks
    Kobi

  • You can't do the software reset from within an ISR because an IRET will never be executed. This means that the 8051 interrupt mechanism will not be reset and no further interrupts of equal or lower priority will be serviced.

    You must do your software reset from non-ISR code with all interrupts disabled.

    Remember that this method is not a real reset - you are just restarting your code.

    Why do you need to do a software reset anyway?

    Stefan

  • "I don't want to waste another pin for hardware reset."

    But in your code:

      while(P3_2 == 0) // Until the LID is open
      {
    
      }
    
      (*((const void(code*)(void)) 0x0000 ))();
    Aren't you effectively trying to use P3.2 as a reset input anyway?

  • Hi

    The Interrupt routine is stucked also if the reset funtion is out of the interrupt routine.
    According to my debugging in some situation during the program execution the program is stucked after the while and in some cases the reset is working properly.

    The question is why in some cases the program is stucked after the while.


    Thanks Kobi

  • You haven't explained why you want to do this software reset. Perhaps you could restructure your program so that you don't need to do it?

    I notice you're doing quite a bit of stuff in your ISR. If you want to make your life a whole lot easier:

    1) Don't call functions from ISRs.
    2) Don't do anything that takes more than a few tens or hundreds of microseconds in the ISR.
    3) Try to avoid modifying multi-byte variables in the ISR.

    All of the above can be done safely but require you to be fully aware of all the implications.

    The 'usual' structure for a program that handles interrupts is:

    In the ISR only do things that are absolutely time critical. Set a bit flag so that the main program loop knows that the interrupt has occurred and can take whatever other action is required.

    If you stick to these guidelines you will probably spend a lot less time wondering why your program mysteriously hangs or misbehaves.

    Stefan