2023-05-16 02:59 AM
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();
}
2023-05-16 03:41 AM
How did you reprogram WDG_HALT in option byte 3 (OPT3)?
2023-05-16 03:46 AM
i just added an example
2023-05-16 04:10 AM
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
2023-05-16 04:24 AM
That didn't change the behavior.
Looking for
while (!(sfr_FLASH.IAPSR.HVOFF))
;
didnt fix the issue
/Peter
2023-05-16 04:32 AM
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.
2023-05-16 04:59 AM
i read it back via stm8flash and saw that the bit was set.
But good point i will try to read it back runtime
2023-05-25 06:18 AM
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.
2023-06-06 12:42 AM
Any updates @Peter BENSCH
2023-06-06 01:55 AM
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