Skip to main content
Visitor II
May 16, 2023
Question

Stop iwdg in halt mode on STM8L051F3

  • May 16, 2023
  • 10 replies
  • 3505 views

Hey

I have tried to use the option byte to stop the iwdg when i enter halt.

I can see that i manage to set the WDG_HALTin option byte 3.

But the watchdog still resets the MCU after i enter halt.

Please help me, cant i do it? If so then how do i read that from the documentation.

If i can what am i doing wrong?

I can reproduce the problem with this code:

void halt_test(void) {
 // switch to 16MHz (default is 2MHz)
 sfr_CLK.CKDIVR.byte = 0x00;
 
 // Setup LED
 sfr_PORTB.DDR.DDR2 = 1; // input(=0) or output(=1)
 sfr_PORTB.CR1.C12 = 1; // input: 0=float, 1=pull-up; output: 0=open-drain, 1=push-pull
 
 // Disable LED
 sfr_PORTB.ODR.ODR2 = 1;
 
 for (uint32_t i = 0; i < 600000; i++) {
 NOP();
 }
 
 // unlock w/e access to EEPROM & option bytes
 sfr_FLASH.DUKR.byte = 0xAE;
 sfr_FLASH.DUKR.byte = 0x56;
 
 // wait until access granted
 while (!(sfr_FLASH.IAPSR.DUL))
 ;
 
 // Enable write to option bytes
 sfr_FLASH.CR2.OPT = 1;
 
 // Set IWDG_HALT bit
 sfr_OPT.OPT3.byte = 0b10;
 
 // wait until end of programming
 while (!(sfr_FLASH.IAPSR.EOP))
 ;
 
 // Disable write to option bytes
 sfr_FLASH.CR2.OPT = 0;
 
 // lock EEPROM again against accidental erase/write
 sfr_FLASH.IAPSR.DUL = 0;
 
 // start IDWG (must be the first value written to this register, see UM)
 sfr_IWDG.KR.byte = (uint8_t)0xCC;
 
 // unlock write access to prescaler and reload registers
 sfr_IWDG.KR.byte = (uint8_t)0x55;
 
 sfr_IWDG.PR.PR = 6;
 
 // set timeout period 0xff = 1724.63ms according to RM0031
 sfr_IWDG.RLR.byte = 0xff;
 
 // start IDWG
 sfr_IWDG.KR.byte = (uint8_t)0xCC;
 
 // Enable LED
 sfr_PORTB.ODR.ODR2 = 0;
 
 ENTER_HALT();
}

    This topic has been closed for replies.

    10 replies

    Technical Moderator
    May 16, 2023

    How did you reprogram WDG_HALT in option byte 3 (OPT3)?

    PRasm.3Author
    Visitor II
    May 16, 2023

    i just added an example

    Technical Moderator
    May 16, 2023

    It looks like you are asking for the wrong bit to test in line 31.

    Instead of EOP you should query HVOFF (see RM0031, section 3.6.2).

    Regards

    /Peter

    PRasm.3Author
    Visitor II
    May 16, 2023

    That didn't change the behavior.

    Looking for

     while (!(sfr_FLASH.IAPSR.HVOFF))
     ;

    didnt fix the issue

    /Peter

    Technical Moderator
    May 16, 2023

    Have you checked the value of OPT3 after trying to program it?

    You could extend the query in line 31 to WR_PG_DIS | HVOFF. 

    PRasm.3Author
    Visitor II
    May 16, 2023

    i read it back via stm8flash and saw that the bit was set.

    But good point i will try to read it back runtime

    PRasm.3Author
    Visitor II
    May 25, 2023
    void halt_test(void) {
     // switch to 16MHz (default is 2MHz)
     sfr_CLK.CKDIVR.byte = 0x00;
     
     // Setup LED
     sfr_PORTB.DDR.byte = 0xff; // input(=0) or output(=1)
     sfr_PORTB.CR1.byte = 0xff; // input: 0=float, 1=pull-up; output: 0=open-drain, 1=push-pull
     
     // Disable LED
     sfr_PORTB.ODR.byte = 0xff;
     
     for (uint32_t i = 0; i < 600000; i++) {
     NOP();
     }
     
     // unlock w/e access to EEPROM & option bytes
     sfr_FLASH.DUKR.byte = 0xAE;
     sfr_FLASH.DUKR.byte = 0x56;
     
     // wait until access granted
     while (!(sfr_FLASH.IAPSR.DUL))
     ;
     
     // Enable write to option bytes
     sfr_FLASH.CR2.OPT = 1;
     
     // Set IWDG_HALT bit
     sfr_OPT.OPT3.byte = 0b10;
     
     // wait until end of programming
     while (!(sfr_FLASH.IAPSR.EOP))
     ;
     
     while ((sfr_FLASH.IAPSR.WR_PG_DIS))
     ;
     
     while (!(sfr_FLASH.IAPSR.HVOFF))
     ;
     
     // Disable write to option bytes
     sfr_FLASH.CR2.OPT = 0;
     
     // lock EEPROM again against accidental erase/write
     sfr_FLASH.IAPSR.DUL = 0;
     
     if (sfr_OPT.OPT3.byte == 0b10) {
     sfr_PORTB.ODR.ODR3 = 0; // LED5
     } else {
     sfr_PORTB.ODR.ODR7 = 0; // LED1
     }
     
     // start IDWG (must be the first value written to this register, see UM)
     sfr_IWDG.KR.byte = (uint8_t)0xCC;
     
     // unlock write access to prescaler and reload registers
     sfr_IWDG.KR.byte = (uint8_t)0x55;
     
     sfr_IWDG.PR.PR = 6;
     
     // set timeout period 0xff = 1724.63ms according to RM0031
     sfr_IWDG.RLR.byte = 0xff;
     
     // start IDWG
     sfr_IWDG.KR.byte = (uint8_t)0xCC;
     
     // Enable LED
     sfr_PORTB.ODR.ODR2 = 0;
     
     ENTER_HALT();
    }

    I have now tried to read OPT3 back runtime and from what i can see the correct bit is set.

    PRasm.3Author
    Visitor II
    June 6, 2023

    Any updates @Peter BENSCH​ 

    Technical Moderator
    June 6, 2023

    Unfortunately, I can only check it theoretically/from memory at the moment and not on a living object, as I don't have one at my place.

    Maybe someone else can be found who has a board with the STM8L051 right now?

    Regards

    /Peter

    PRasm.3Author
    Visitor II
    June 6, 2023

    No worries, i just saw you listed as an employee i guessed you had access to the board.

    Do you know how to get in contact with somebody at st that have access to the chip?

    Visitor II
    June 6, 2023

    Are you sure the watchdog resets while in halt?

    Maybe program doesn't stop in halt.

    PRasm.3Author
    Visitor II
    June 8, 2023

    I think i found the problem, but im not entirely sure why.

    For start watchdog i set the KR register to CC in the code example. If i set it to AA instead everything seems to work as expected.

    Would anybody know why that change would matter? I guess by reading the datasheet AA makes more sense but its not clear to me

    Visitor II
    June 8, 2023

    Maybe value AA doesn't start watchdog. So reset doesn't occur.

    From datasheet value AA starts watchdog, value CC refreshes watchdog.