COMP (or PPI) drops event

Hi,

I previously wrote about an unexpected behaviour which I've made a diagram for below. It's relatively simple though, the COMP watches a voltage and fires a toggle event through PPI which is received by GPIOTE which toggles it's pin which controls an external circuit responsible for the voltage that COMP watches.

First the external circuit is switched off by a secondary means and the system is synced, so GPIOTE goes high and COMP goes high, then the secondary means is turned off so the driver activates and then it's purely a hardware based implementation.

I previously replicated the behaviour when the COMP speed was set to normal. This suggested that PPI or GPIOTE couldn't keep up with the events it was generating OR COMP was/is sometimes failing to generate the toggle event when the voltage has recovered. The behaviour means the GPIOTE remains low when the voltage has recovered.

The COMP speed was set to low, so 1MHz, and on the bench this appeared to have resolved the issue. However, a user is now reporting it again.



  • Hi snoopy20,

    Firstly, regarding your conclusion that either PPI or GPIOTE isn't able to keep up with 1MHz COMP, I will have to ask about this in my internal query as well before I can confirm it.

    However, I am still unclear on one detail. Does the system run in some kind of loop then? And what is the frequency of looping then?

    Secondly, here is my understanding of the system, please correct me if I am wrong.

    • It is meant to be a UVLO monitoring VDD
    • The TLV62090 converts VDD to a lower voltage for a sink
    • The COMP+PPI+GPIOTE setup controls the TLV62090

    I think I am missing a few more things:

    • How the TLV62090 and later circuits affects VDD? Is it just a voltage dip due to sudden loading?
    • How frequently does this loop repeat?
    • Can you give a state machine showing how the COMP, GPIOTE, and TLV62090 are supposed to work together?

    Thirdly, regarding the RTC workaround you are setting up, could you please tell me exactly which PPI event is connected to which PPI tasks over which PPI channels, one at a time?

  • The frequency of the loop is dictated by the speed of the COMP, which in low power mode is 1MHz according to the datasheet.

    Your understanding of the system is correct. Then your third points are:

    1. correct, if the sink is too much VDD will drop
    2. the speed of the missing event (Vdd recovered) is dependent on how fast TLV62090 turns off and then how fast COMP toggles its state. The turn off by TLV62090 will be very fast, microseconds at worst. The state (Vdd recovered) is then waiting for COMP to detect it.
    3. there's really not much to it. COMP detects Vdd, state goes to PPI/GPIOTE and toggles thing which affects Vdd, so equilibrium.

    The PPI GRP workaround is a success (the RTC is just to clock, could use anything). I've ran it for hours.

    The solutions slows down the EVENT_UP propagation and so clearly tells me the problem is not with COMP or PPI because it's now working, so the problem is with GPIOTE. It isn't fast enough to handle 1MHz PPI events.

      // GPIOTE turn-offs
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR].EEP = (uint32_t) &NRF_COMP->EVENTS_DOWN;
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR].TEP = (uint32_t) &NRF_GPIOTE->TASKS_CLR[CFG_GPIOTE_POWERMANAGER_FRONT];
      NRF_PPI->FORK[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR].TEP = (uint32_t) &NRF_GPIOTE->TASKS_CLR[CFG_GPIOTE_POWERMANAGER_REAR];
    
      // -- enables first group, awaits a tick
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_GROUP].EEP = (uint32_t) &NRF_COMP->EVENTS_UP;
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_GROUP].TEP = (uint32_t) &NRF_PPI->TASKS_CHG[CFG_PPI_GROUP_POWERMANAGER_ENABLE_NEXT].EN;
    
      // -- enables next group on tick, disables self (one shot)
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_TIMER_GROUP_NEXT].EEP = (uint32_t) &CFG_SCHEDULER_TIMER->EVENTS_TICK;
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_TIMER_GROUP_NEXT].TEP = (uint32_t) &NRF_PPI->TASKS_CHG[CFG_PPI_GROUP_POWERMANAGER_ENABLE_NEXT].DIS;
      NRF_PPI->FORK[CFG_PPI_POWERMANAGER_TIMER_GROUP_NEXT].TEP = (uint32_t) &NRF_PPI->TASKS_CHG[CFG_PPI_GROUP_POWERMANAGER_ENABLE_SET].EN;
      NRF_PPI->CHG[CFG_PPI_GROUP_POWERMANAGER_ENABLE_NEXT] = 1 << CFG_PPI_POWERMANAGER_TIMER_GROUP_NEXT;
    
      // -- sets outputs, disables self (one shot)
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_TIMER_FRONTREAR].EEP = (uint32_t) &CFG_SCHEDULER_TIMER->EVENTS_TICK;
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_TIMER_FRONTREAR].TEP = (uint32_t) &NRF_GPIOTE->TASKS_SET[CFG_GPIOTE_POWERMANAGER_FRONT];
      NRF_PPI->FORK[CFG_PPI_POWERMANAGER_TIMER_FRONTREAR].TEP = (uint32_t) &NRF_GPIOTE->TASKS_SET[CFG_GPIOTE_POWERMANAGER_REAR];
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_TIMER_GROUP_SET].EEP = (uint32_t) &CFG_SCHEDULER_TIMER->EVENTS_TICK;
      NRF_PPI->CH[CFG_PPI_POWERMANAGER_TIMER_GROUP_SET].TEP = (uint32_t) &NRF_PPI->TASKS_CHG[CFG_PPI_GROUP_POWERMANAGER_ENABLE_SET].DIS;
      NRF_PPI->CHG[CFG_PPI_GROUP_POWERMANAGER_ENABLE_SET] = 1 << CFG_PPI_POWERMANAGER_TIMER_FRONTREAR | 1 << CFG_PPI_POWERMANAGER_TIMER_GROUP_SET;


    I hope you like the solution, I'm pretty pleased with myself. With NRF52 there's always a way. Sunglasses



  • I am afraid I am unqualified to comment on this solution Sweat smile. I see what you are doing, but I lack the knowledge to evaluate it.

    But it's great to know that you have a working solution now.

    I will follow-up regarding the unanswered questions once I receive a response for my internal query. However, it looks like that has to be after the Easter holiday. My apology for the inconvenience.

  • Sure, there's no rush, the 'solution' is working and everyone is happy.

Related