cembeddedstm32stm32f1

STM32F103 chip keeps resetting about every 500ms


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);
}

Solution

  • 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.