Level based control of GPIOTE



Hi,

I have a comparator acting as a UVLO, it connects to a NRF52 pin with a pull-up. The comparator also pulls down two other circuits using a diode, which in turn are connected to other NRF52 pins using pull-ups. It works well.

I'd like if possible to remove the diodes and connecting the UVLO signal via GPIO Event through PPI and controlling the other two pins via GPIOTE SET and CLEAR.

What I can't determine from the datasheet is whether once the initial output of GPIOTE is set if PPI & GPIOTE are fully async to the clock in which case it would be like level control where they couldn't miss an event, or whether the clock is working to determine the event (like a D gate) in which case potentially the event could be missed.

It is only a small optimisation but one I thought I'd look at as I was contemplating moving the comparator to the built-in one.

Andrew

Parents
  • Hi,

     

    What I can't determine from the datasheet is whether once the initial output of GPIOTE is set if PPI & GPIOTE are fully async to the clock in which case it would be like level control where they couldn't miss an event, or whether the clock is working to determine the event (like a D gate) in which case potentially the event could be missed.

    If I understand the scenario correct, you want two IN channels to, based on falling/rising edge-triggering, SET/CLR two other GPIOs. Please correct me if I'm mistaken.

    GPIOTE IN/OUT, when connected through PPI, will be synchronous to the internal 16 MHz peripheral clock.

    If more than one operation occurs on the same clock cycle, one event can be postponed to the next clock cycle.

     

    There is however one scenario that can occur, which is errata #155:

    https://infocenter.nordicsemi.com/topic/errata_nRF52810_Rev3/ERR/nRF52810/Rev3/latest/anomaly_810_155.html?cp=5_5_1_0_1_12

     

    If you have two GPIOTE IN channels occurring within the timed scope (ie. < 1.3 us apart), you will hit this errata. 

    The side-effect of this errata workaround is higher current consumption, as the peripheral clock tree will be kept in sleep mode.

     

    Kind regards,

    Håkon

  • Hi,

    LMV393 has a propagation of 0.2us, which is 5 MHz.

    As you say it's synchronous to the 16MHz clock, so let's say at max there are 5 edges at 0.2us apart. Would PPI/GPIOTE be able to keep up driving an output pin using the SET/CLEAR events?

    It sounds like it would, so long as the propagation didn't take more than 3 clock cycles.

  • Hi,

     

    snoopy20 said:
    1. turn both off using GPIOTE_CONFIG_MODE_Disabled

    This will disable GPIOTE channel, and not really do anything with the state of the GPIO itself.

    This is highly likely not the functionality you're after.

    snoopy20 said:
    I may have a solution, if I leave GPIOTE Task enabled but instead switch GPIO to be an input with a pull-down enabled...?

    No, but you can use more PPI channels to ensure that other GPIOTE OUT channels are set in your wanted state at that time.

     

    Can you share a diagram or similar on how you want your GPIOs to be set in each COMP state?

     

    Kind regards,

    Håkon

  • This reply was deleted.
  • Been looking into it this evening. I read that GPIO config is retained when GPIOTE takes over the pin output. I'm unsure but making an assumption that weak pull is still operational when pin is in outmode mode. A hopeful solution is:
      

    NRF_GPIO->PIN_CNF[CFG_PIN_POWERMANAGER_FRONT_ENABLE] = pinDisconnectInputBuffer 
        | GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos 
        | GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos 
        | GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos;
      
    NRF_GPIOTE->CONFIG[CFG_GPIOTE_POWERMANAGER_FRONT] = GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos 
        | GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos 
        | CFG_PIN_POWERMANAGER_FRONT_ENABLE << GPIOTE_CONFIG_PSEL_Pos;
    
    NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR_GOOD].EEP = (uint32_t) &NRF_COMP->EVENTS_UP;
    NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR_GOOD].TEP = (uint32_t) &NRF_GPIOTE->TASKS_SET[CFG_GPIOTE_POWERMANAGER_FRONT];
    NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR_BAD].EEP = (uint32_t) &NRF_COMP->EVENTS_DOWN;
    NRF_PPI->CH[CFG_PPI_POWERMANAGER_UVLO_FRONTREAR_BAD].TEP = (uint32_t) &NRF_GPIOTE->TASKS_CLR[CFG_GPIOTE_POWERMANAGER_FRONT];
    
    // UVLO
    NRF_COMP->REFSEL = UVLO_REFERENCE << COMP_REFSEL_REFSEL_Pos;
    NRF_COMP->TH = UVLO_HYSTERESIS_UP << COMP_TH_THUP_Pos | UVLO_HYSTERESIS_DOWN << COMP_TH_THDOWN_Pos;
    NRF_COMP->PSEL = COMP_UVLO << COMP_PSEL_PSEL_Pos;
    NRF_COMP->ENABLE = COMP_ENABLE_ENABLE_Enabled << COMP_ENABLE_ENABLE_Pos;
    NRF_COMP->TASKS_SAMPLE = COMP_TASKS_SAMPLE_TASKS_SAMPLE_Trigger << COMP_TASKS_SAMPLE_TASKS_SAMPLE_Pos;
    
    // wait a moment for voltage to stablize
    // if it doesn't happen watchdog will reset
    while (!NRF_COMP->RESULT) {
      NRF_COMP->TASKS_SAMPLE = 1;
    };
    NRF_COMP->EVENTS_DOWN = 0;
    
    // must come after comparator to ensure output sync
    NRF_PPI->CHENSET = 1 << CFG_PPI_POWERMANAGER_UVLO_FRONTREAR_GOOD
      | 1 << CFG_PPI_POWERMANAGER_UVLO_FRONTREAR_BAD
      | 1 << CFG_PPI_POWERMANAGER_UVLO_USB_BAD;

    Then to enable the pin

    NRF_GPIO->PIN_CNF[CFG_PIN_POWERMANAGER_FRONT_ENABLE] = pinDisconnectInputBuffer 
        | GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos 
        | GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos;


    And to disable it again

    NRF_GPIO->PIN_CNF[CFG_PIN_POWERMANAGER_FRONT_ENABLE] = pinDisconnectInputBuffer 
        | GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos 
        | GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos 
        | GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos;

  • Hi,

     

    A pull-resistor cannot be enabled on a output device, so the GPIO_PIN_CNF_PULL line does not have any effect when the GPIO is configured with GPIO_PIN_CNF_DIR_Output.

     

    When you disable, you have setup the specific GPIO to be a open-drain, commonly used in I2C pin operation.

    The drive-level is set to standard-drive on '0' (output low), and disconnected on output high '1'.

    This means that the GPIO will float when set to '1'.

     

    You have 3 states:

    * EVENTS_DOWN

    * EVENTS_UP

    * "default state"

     

    How do you want your GPIO(s) to be set in each of these states?

     

    Kind regards,

    Håkon

  • EVENTS_DOWN = task, 0,  GPIO_PIN_CNF_DRIVE_S0S1 
    EVENTS_UP = task, 1, GPIO_PIN_CNF_DRIVE_S0S1 
    DEFAULT (OVERRIDE) = external weak pull-down, GPIO_PIN_CNF_DRIVE_S0D1

    The diagram within the gpio section indicates drive_strength will be respected. I only need to add an external weak-pull down resistor.

Reply Children
No Data
Related