Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Watchdog is resetting the Controller for every 6 times of reset done by the NVIC_system reset() #34

Open
sadikthanos opened this issue Dec 8, 2023 · 4 comments

Comments

@sadikthanos
Copy link

The issue is that I am resetting the application using the function NVIC_System_reset() function whenever Our device does not connect to the Cloud application through the Ethernet then after every 6 iterations I will get a Log saying that Reboot has happened due to the Watchdog reset and I verified it using SYS->RSTSTS register.

Note: The issue does not occur when I perform the WDT_RESET_COUNTER(); before ding NVIC_system_reset();

I have verified all of the registers related to the WDT peripheral as per the User Manual and No clue is found regarding the issue with the relation of multiple NVIC system reset() and Watchdod reboot after booting Up.

Platform : Mbed OS
Compiler: ARM C6

I am using the m487sidae microcontroller and below code is the Initializations of the Watchdog and the WDT_IrqHandler() functions.

void mbed_sdk_init(void)
{

static int inited = 0;
if (inited) {
    return;
}
inited = 1;

/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
SYS_UnlockReg();

/* Enable HIRC clock (Internal RC 22.1184MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);
/* Enable HXT clock (external XTAL 12MHz) */
CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);
/* Enable LIRC for lp_ticker */
CLK_EnableXtalRC(CLK_PWRCTL_LIRCEN_Msk);
/* Enable LXT for RTC */
CLK_EnableXtalRC(CLK_PWRCTL_LXTEN_Msk);

/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Wait for HXT clock ready */
CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
/* Wait for LIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_LIRCSTB_Msk);
/* Wait for LXT clock ready */
CLK_WaitClockReady(CLK_STATUS_LXTSTB_Msk);

/* Select HCLK clock source as HIRC and HCLK clock divider as 1 */
CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));


// CLK_EnableModuleClock(WDT_MODULE);
CLK_EnableModuleClock(I2C0_MODULE);

// CLK_SetModuleClock(WDT_MODULE, CLK_CLKSEL1_WDTSEL_LIRC, 0);


/* Set core clock as 192000000 from PLL */
CLK_SetCoreClock(192000000);

/* Set PCLK0/PCLK1 to HCLK/2 */
CLK->PCLKDIV = (CLK_PCLKDIV_PCLK0DIV2 | CLK_PCLKDIV_PCLK1DIV2); 

#if DEVICE_ANALOGIN
/* Vref connect to internal */
SYS->VREFCTL = (SYS->VREFCTL & ~SYS_VREFCTL_VREFCTL_Msk) | SYS_VREFCTL_VREF_3_0V;
#endif

 /* Set I2C0 multi-function pins */
SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA5MFP_Msk | SYS_GPA_MFPL_PA4MFP_Msk);
SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA5MFP_I2C0_SCL | SYS_GPA_MFPL_PA4MFP_I2C0_SDA);

// I2C clock pin enable schmitt trigger
PA->SMTEN |= GPIO_SMTEN_SMTEN5_Msk;


SystemCoreClockUpdate();

GPIO_SetMode(PA,BIT9,GPIO_MODE_OUTPUT);
GPIO_SetMode(PA,BIT8,GPIO_MODE_OUTPUT);
GPIO_SetMode(PF,BIT7,GPIO_MODE_OUTPUT);
PA8 = 1;
PA9 = 1;
PF6 = 1;
//printf("\n\n hal init Setting WDT \n\n");
/* Lock protected registers */
SYS_LockReg();
/* Get around h/w issue with reset from power-down mode
 *
 * When UART interrupt enabled and WDT reset from power-down mode, in the next
 * cycle, UART interrupt keeps breaking in and cannot block unless via NVIC. To
 * get around it, we make up a signal of WDT wake-up from power-down mode in the
 * start of boot process on detecting WDT reset.
 */

// printf("reset_status_register_is--->%8x\n\r",SYS->RSTSTS);

 
if (SYS_IS_WDT_RST()) {

    /* Enable IP module clock */
    CLK_EnableModuleClock(WDT_MODULE);

    /* Select IP clock source */
    CLK_SetModuleClock(WDT_MODULE, CLK_CLKSEL1_WDTSEL_LIRC, 0);

    /* The name of symbol WDT_IRQHandler() is mangled in C++ and cannot
     * override that in startup file in C. Note the NVIC_SetVector call
     * cannot be left out when WDT_IRQHandler() is redefined in C++ file.
     *
     * NVIC_SetVector(WDT_IRQn, (uint32_t) WDT_IRQHandler);
     */
    NVIC_EnableIRQ(WDT_IRQn);

    NVIC_SetVector(WDT_IRQn, (uint32_t) WDT_IRQHandler);

    SYS_UnlockReg();

    /* Configure/Enable WDT */
    WDT->CTL = WDT_TIMEOUT_2POW4 |      // Timeout interval of 2^4 LIRC clocks
            WDT_CTL_WDTEN_Msk |         // Enable watchdog timer
            WDT_CTL_INTEN_Msk |         // Enable interrupt
            WDT_CTL_WKF_Msk |           // Clear wake-up flag
            WDT_CTL_WKEN_Msk |          // Enable wake-up on timeout
            WDT_CTL_IF_Msk |            // Clear interrupt flag
            WDT_CTL_RSTF_Msk |          // Clear reset flag
            !WDT_CTL_RSTEN_Msk |        // Disable reset
            WDT_CTL_RSTCNT_Msk;         // Reset up counter

    CLK_PowerDown();

    /* Clear all flags & Disable WDT/INT/WK/RST */
    
    WDT->CTL = (WDT_CTL_WKF_Msk | WDT_CTL_IF_Msk | WDT_CTL_RSTF_Msk | WDT_CTL_RSTCNT_Msk);

    NVIC_DisableIRQ(WDT_IRQn);

    SYS_LockReg();
}


SYS_UnlockReg();
NVIC_EnableIRQ(WDT_IRQn);

NVIC_SetVector(WDT_IRQn, (uint32_t) WDT_IRQHandler);

SYS_UnlockReg();

 I2C_Open(I2C0, 100000);

WDT_Open(WDT_TIMEOUT_2POW18, WDT_RESET_DELAY_1026CLK, TRUE, TRUE);
 WDT_EnableInt();

}

WDT_IRQHandler function is below

void WDT_IRQHandler(void)
{

SYS_UnlockReg();

WDT_RESET_COUNTER_IN_CTL();

WDT_RESET_COUNTER();


/* Check WDT interrupt flag */
if (WDT_GET_TIMEOUT_INT_FLAG()) {
    WDT_CLEAR_TIMEOUT_INT_FLAG(); 

}

/* Check WDT wake-up flag */
if (WDT_GET_TIMEOUT_WAKEUP_FLAG()) {
    WDT_CLEAR_TIMEOUT_WAKEUP_FLAG();
}

}

@Michael050492
Copy link

Hi,
I think NVIC_System_reset() causes an MCU resest but WDTEN and RSTEN are not affected.
In the System reset chapter, you can see which registers keep their original settings after reset.

Is it possible that WDT_RESET_COUNTER() is not executed when WDT is enabled after executing NVIC_System_reset()?

@sadikthanos
Copy link
Author

Hi @Michael050492 ,

Thanks for the reply.

Is it possible that WDT_RESET_COUNTER() is not executed when WDT is enabled after executing NVIC_System_reset()?

I have verified all the registers related to the WDT and System reset, But none of them shows any signs of interrupts raised for the WDT.

Here is the NVIC_Sytem_reset() function :
image

I have few questions to ask regarding this matter.

  1. Is it possible that when the system is rebooted using NVIC_system_reset(), the Watchdog Timer (WDT) interrupt is triggered immediately, and the execution of IRQHandler() is hindered as it is in a reset state?
  2. Is there a method to access the Watchdog Timer (WDT) counter value to verify whether the counter register is incremented just before or after the execution of NVIC_system_reset()?
  3. After invoking NVIC_system_reset(), all peripherals are reset, and during the subsequent bootup process, each peripheral is reinitialized. This process should eliminate the possibility of the Watchdog Timer (WDT) not running after each NVIC_system_reset().

The strange behaviour is that today I removed all other features in our firmware and just rebooted the application start of the main(),

Observation: With the above scenarion The WDT reboot happenend after just 2 NVIC_system_resets() and after that no sort of reboot happenned due to the WDT eventhough the system is continuosly rebooted by NVIC_system_reset().

image

@ychuang3
Copy link
Contributor

I suggest to use SYS_ResetChip(), instead of NVIC_System_reset().
NVIC_System_reset() will make M4 core reset, but it will not make peripheral IP reset.
SYS_ResetChip() will make the whole chip reset, just like press the reset button.
It will also reset WDT.

SYS_ResetChip() is M480 specific.

@sadikthanos
Copy link
Author

sadikthanos commented Dec 11, 2023

I suggest to use SYS_ResetChip(), instead of NVIC_System_reset(). NVIC_System_reset() will make M4 core reset, but it will not make peripheral IP reset. SYS_ResetChip() will make the whole chip reset, just like press the reset button. It will also reset WDT.

@ychuang3 , Yeah we can use the SYS_ResetChip() but if you look at our Memory layout of the Flash memory as shown in below picture. If we perform SYS_ResetChip() everytime the Loader will be booted. So , we dont want the Loader to be booted thats why we are using NVIC_System_reset() as it will boot the application from 0x6000 address.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants