Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

PSoC™ 4 Forum Discussions

PeteFirmware
Level 1
First reply posted First question asked Welcome!
Level 1

Completely out of my comfort zone, started coding firmware 1 week ago from scratch, building on firmware with BLE we have had for years.

We have a WDT counter0 that mainly resets the system if 3 consecutive interrupts are unresolved.

We have WDT counter1 that interrupts once per second and reads an array of sensors.

This system works relatively well, although it can brown out or simply power down unexpectedly about once per month. It also resets every now and then, which is fine.

 

I would like to introduce WDT counter 2 (set as interrupt) to put pressure on the system. We are theorizing that our WDT interrupts might be colliding with component (BLE?) interrupts, resulting in an unknown state.

I can set up counter 2 normally, and it triggers at the interval I am expecting. However, it seems that the interrupts are not cleared properly. In fact, the CY_ISR (newFunction) does not even run when the counter reaches it's toggle bit. Is there something I need to enable that is different from WDT0 and 1? I know it cannot clear itself and cannot match number.

I can provide code example, but would need to remove proprietary sections. So I'm making a higher level inquiry first.

0 Likes
3 Replies
PratikshaV
Moderator
Moderator 100 replies posted 25 solutions authored 100 sign-ins
Moderator

Hi @PeteFirmware 

Please can you check with the priorities of the  interrupts can you set priority 0 for BLE and 1 for WDT and check once or else please can you share your code so that we can check at our end.

 

Thanks & Regards

Pratiksha V

0 Likes
PeteFirmware
Level 1
First reply posted First question asked Welcome!
Level 1

I've attached an image of the interrupts that show up under system wide resources. BLE_BLESS is the highest priority, although it's not 0. I have WDT2 code switchable by a #if clause. When turned off everything works fine. When turned on it consistently resets after 32 seconds, which corresponds to 2x the togglebit on WDT2.

Hopefully, this extracted code makes sense.  Timer_Interrupt ISR triggers fine. Tester ISR does not, although WDT2 clearly feeds WDT0 with unresolved interrupts. I've played around with the placement of CySysWdtClearInterrupt for WDT2 quite a bit, putting it in main loop, Tester ISR, separate function etc. I have searched online extensively for code examples with WDT2, but it is much less used than 0 and 1. I must be missing something fundamental.

 

void WDT_Reset()

{

    //feed the hardware watchdog

    CySysWdtUnlock();

    CySysWdtResetCounters(CY_SYS_WDT_COUNTER0_RESET);

    CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER0_INT);

    CySysWdtLock();

}

 

 

#if TEST_EXTRA_ISR == ENABLED

CY_ISR(Tester) {

    void ClearWDT2();

}

 

void ClearWDT2( void )

{

    CySysWdtClearInterrupt(CY_SYS_WDT_COUNTER2_INT);

}

#endif

 

 

CY_ISR(Timer_Interrupt) // 1Hz

{

    Interrupt_Function1();

   

    return;

}

 

 

void StartWDT( void )

{

    /* Unlock the WDT registers for modification */

    CySysWdtUnlock();

    /* Setup ISR */

   

    #if TEST_EXTRA_ISR == ENABLED

    /*==============================================================================*/

    /* configure counter 2 for testing                               */

    /*==============================================================================*/

    /* Register Tester () by the WDT COUNTER2 which will generate an interrupt*/

    CySysWdtSetInterruptCallback(CY_SYS_WDT_COUNTER2, Tester);

    isrTimer_StartEx(&Tester);

   

    /* Write the mode to generate interrupt on bit toggle */

    CySysWdtWriteMode(CY_SYS_WDT_COUNTER2, CY_SYS_WDT_MODE_INT);

    /*Set the bit at which the WDT will trigger and execute Tester*/

    CySysWdtWriteToggleBit(TEST_TIMER);

 

    #endif

 

     /*==============================================================================*/

     /* configure counter 1 for period 1st interrupt                                 */

     /*==============================================================================*/

     /* Register Timer_Interrupt() by the WDT COUNTER1 which will generate an interrupt

        every second */

    CySysWdtSetInterruptCallback(CY_SYS_WDT_COUNTER1, Timer_Interrupt);

    isrTimer_StartEx(&Timer_Interrupt);

   

    /* Write the mode to generate interrupt on match */

    CySysWdtWriteMode(CY_SYS_WDT_COUNTER1, CY_SYS_WDT_MODE_INT);

    /* Configure the WDT counter clear on a match setting */

    CySysWdtWriteClearOnMatch(CY_SYS_WDT_COUNTER1, ENABLED);

    /* Configure the WDT counter match comparison value */

    CySysWdtWriteMatch(CY_SYS_WDT_COUNTER1, TIMER_MATCH);

   

     /*==============================================================================*/

     /* configure counter 0 for system reset                                         */

     /*==============================================================================*/

    /* Counter 0 of watchdog generates peridically interrupt and a

       reset is generated on the the third unhandled interrupt */

    CySysWdtWriteMode(CY_SYS_WDT_COUNTER0, CY_SYS_WDT_MODE_RESET);

    /* Set interval as desired value */

      CySysWdtWriteMatch(CY_SYS_WDT_COUNTER0, WDT_RESET_MATCH);

    /* clear counter on match event */

      CySysWdtWriteClearOnMatch(CY_SYS_WDT_COUNTER0, 1u);

   

    /* Reset WDT counter */

    CySysWdtResetCounters(CY_SYS_WDT_COUNTER0_RESET);

    CySysWdtResetCounters(CY_SYS_WDT_COUNTER1);

    CySysWdtResetCounters(CY_SYS_WDT_COUNTER2);

    /* Enable the specified WDT counter */

    CySysWdtEnable(CY_SYS_WDT_COUNTER1_MASK);

    CySysWdtEnable(CY_SYS_WDT_COUNTER0_MASK);

    CySysWdtEnable(CY_SYS_WDT_COUNTER2_MASK);

    /* Lock out configuration changes to the Watchdog timer registers */

    CySysWdtLock();

        

    return;

}

 

int main()

{

/* Enable global interrupts */

    CyGlobalIntEnable;

StartWDT();

/* Extracts from Main Loop*/

While(1) {

WDT_Reset();

CyBle_ProcessEvents();

        CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP);

0 Likes
PeteFirmware
Level 1
First reply posted First question asked Welcome!
Level 1

One theory I have is that two CY_ISR functions are not allowed by our controller. So CY_ISR(Tester) cannot trigger, which means I'd have to do an if statement differentiating the source of the counter to trigger the function I want.

Anyone knows how to extract which WDT counter was activated? I used this code, which failed spectacularly:

CY_ISR(Timer_Interrupt) // 1Hz
{
uint32 intSource = CySysWdtGetInterruptSource();

/* if interrupt is generated by COUNTER 1 */
if((intSource & CY_SYS_WDT_COUNTER1_INT) == CY_SYS_WDT_COUNTER1_INT)
{
Interrupt_Function1();
}
/* if interrupt is generated by COUNTER 2 */
if((intSource & CY_SYS_WDT_COUNTER2_INT) == CY_SYS_WDT_COUNTER2_INT)
{
DBG_PRINTF(" - WDT2 Triggered! - ");
ClearWDT2();
}

return;
}

0 Likes