0

I wrote a simple blink program for a stm32f103rbt6 chip, but after a while I noticed that MCU is resetting constantly. When I check RCC-CSR register the PINRSTF flag is high. but I didn't connect anything externally to NRST pin. Has anybody an idea that why this occures? Is it possible that anything internally cause this situation?

It's the program that I've written for debugging. the result is that everytime LED wants to turn on but quickly turns off.

#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "system_stm32f10x.h"
#include "delay.h"
#include "output.h"

int main(void){


    RCC_APB2PeriphClockCmd(
        RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin   = PIN_52.pin;
    GPIO_Init(PIN_52.port, &GPIO_InitStructure);
    GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_SET);

    if  (RCC_GetFlagStatus(RCC_FLAG_SFTRST)){
        //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    } else if  (RCC_GetFlagStatus(RCC_FLAG_PORRST)){
        //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    } else if  (RCC_GetFlagStatus(RCC_FLAG_PINRST)){
        GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    } else if  (RCC_GetFlagStatus(RCC_FLAG_IWDGRST)){
        //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    }else if  (RCC_GetFlagStatus(RCC_FLAG_WWDGRST)){
        //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    }else if  (RCC_GetFlagStatus(RCC_FLAG_LPWRRST)){
        //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    }else {
        //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
    }
    RCC_ClearFlag();

    while (1);
}
Clifford
  • 88,407
  • 13
  • 85
  • 165
aygin
  • 109
  • 1
  • 7
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/214637/discussion-on-question-by-aygin-stm32f103-chip-keeps-resetting-about-every-500ms). – Samuel Liew May 26 '20 at 04:28

1 Answers1

2

Your RCC_GetFlagStatus() checks in the if-else if chain detected only the first flag in the ordered list, but these flags are not mutually exclusive, you should check all reset flags.

if( RCC_GetFlagStatus(RCC_FLAG_SFTRST) )
{
    //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}

if( RCC_GetFlagStatus(RCC_FLAG_PORRST) )
{
    //GPIO_WriteBit(PIN_52.port, PIN_52.pin, Bit_RESET);
}

// etc...

Since you have an ST-Link debugger, presumably you have a source-level debugger? In which case rather then trying to debug this on a single LED pin, use the source-level debugger, and place a breakpoint in each status flag check body. Or more simply, but read the entire register in one place:

uint32_t rcc_status = RCC->CSR ;
RCC->CSR |= RCC_CSR_RMVF ;

while(1) ; // breakpoint here

Then inspect rcc_status value in the debugger.

If as seems likely this is an IWDG reset, then either it has been enabled in software in the start-up or a bootloader, or it is enabled in the Option Bytes. You can check that by reading the FLASH_OBR (address 0x4002201C)? It's default value is 0x03FF FFFC - if in your case it is some other value, then the option bytes (which is a special area of flash memory at 0x1FFFF800 - 0x1FFFF80F) have been modified. Specifically if FLASH_OBR bit 2 (0x04 mask) is zero, then the IWDG will run from reset without being specifically set by software. The option bytes are not described in the general STM32F102 user manual UM0008, but rather in the flash programming manual PM0075.

A simple test to demonstrate that it is a watchdog reset is simply to maintain the watchdog in the busy-loop:

while(1)
{
    IWDG_ReloadCounter() ;
}

You can also set/reset the option bytes using the ST-Link Utility.

The IWDG runs from either the 40KHz (nominal but wide variation) RC oscillator, or an external oscillator/crystal on the OSC_32KHz pins. This is normally 32768Hz for an accurate RTC. Anyway the default prescaler is /4 and the default reload is 0x0FFF (4096). So for 32768Hz clock, the default IWDG values will cause a timeout at exactly 500ms (4096/(32768/4)) which is what you have observed. The RC oscilator may range from 30KHz to 60KHz giving a default IWDG range of 273ms to 546ms.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Not really an answer, but too much for a comment. More a how to investigate more effectively that the debug method used in the question. Will update in response to comments or question update @aygin if forthcoming. – Clifford May 25 '20 at 20:32
  • I tried debug mode. It seems to be watchdog problem. But the problem is that I never enable the independent watchdog, and I don't know how to disable it. the RCC_CSR value is: 10 0100 0000 0000 0000 0000 0000 0010. that means the flags PINRSTF & IWDGRSTF are high. – aygin May 25 '20 at 22:00
  • @aygin OK, updated with information about _option bytes_. – Clifford May 25 '20 at 22:49
  • 1
    @aygin : When you state in the question that nothing is connected to the NRST pin, did you have your ST-Link connected? Because that _is_ connected to NRST. – Clifford May 25 '20 at 22:56
  • I just connect the pins 3.3V, GND, SWDIO, SWCLK. – aygin May 26 '20 at 06:25
  • Thank you so much for your support. the problem is solved. :) but I didn't notice how did it occure. It is for a while that I'm working with this chip and never had this issue. I checked the option bytes too. do you have any idea? – aygin May 26 '20 at 06:28
  • @aygin : You have not stated how you solved the problem or the state of the option byte, so I cannot comment. – Clifford May 26 '20 at 06:34
  • I used the watchdog update that you put in the code above. But before it I should've enabled IWDG and enabled WriteAccessCmd. All the option bytes were unchecked. – aygin May 26 '20 at 07:03
  • @aygin I'd say that is a work-around rather than a solution. You need not enable the watchdog since it appeared to already have been enabled. You should inspect the IWDG registers in the debugger _before_ modifying it. If the register values are not at reset defaults, then _something_ has changed them. Set a write-access breakpoint and run from reset to find what is modifying it. Note that "debug" is not a processor "mode"; the CoreSight on-chip debug module is independent of the ARM core. – Clifford May 26 '20 at 07:12
  • In while(1) after IWDG_SetReload(0x0FFF) please add this command IWDG_ReloadCounter(). It doesn't work without RealoadCounter. – aygin May 27 '20 at 13:55
  • 1
    @aygin : Indeed - I was working from memory without access to the API. The `IWDG_SetRelaod()` is not needed at all - it has already been set or is at default. You really should however figure out how to disable it. Be aware the the option bit is zero when the watchdog is _enabled_ - that might be counter intuitive. – Clifford May 27 '20 at 15:55