Configuring the GPIO takes too long?

Hi Nordic Team:

I am developing the firmware for nRF54H20 using NCS v3.2.0. I need to quickly configure 16 GPIOs as input with pull-up resistors, so I adopted the coding approach shown below. However, actual measurements show that executing KEY_IO_CFG_INPUT(); takes about 12 microseconds, whereas it took less than 1 μs on the nRF52840 previously. Is this due to the GPIO access speed limitation of nRF54H20, or is there any configuration that needs to be adjusted? Could anyone help check this issue? thanks.

#define KEY_IO_CFG_INPUT() { \
        NRF_P2->PIN_CNF[0] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P2->PIN_CNF[1] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P2->PIN_CNF[2] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P2->PIN_CNF[3] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P2->PIN_CNF[4] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P2->PIN_CNF[5] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[1] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[2] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[3] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[4] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[5] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[6] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[7] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[8] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[9] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
        NRF_P1->PIN_CNF[10] = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos); \
    }

// P9.0
const struct gpio_dt_spec ktsp1 = GPIO_DT_SPEC_GET(DT_ALIAS(tsp1), gpios);      //test pin, use to toggle io to measure time

int main(void)
{
    gpio_pin_configure_dt(&ktsp1, GPIO_OUTPUT_INACTIVE);

    while(1)
    {
        k_msleep(100);

        k_sched_lock();

        //NRF_P9->OUTSET = 1;
        gpio_pin_configure_dt(&ktsp1, GPIO_OUTPUT_ACTIVE);

        //for(uint32_t i = 0; i < 1000; i++)
        {
            KEY_IO_CFG_INPUT();             // it takes 12us
        }

        gpio_pin_configure_dt(&ktsp1, GPIO_OUTPUT_INACTIVE);
        //NRF_P9->OUTCLR= 1;

        k_sched_unlock();
    }
    return 0;
}

Parents Reply Children
  • Yes, your data is real.

    I had to look it up, turns out GPIO is an AHB peripherial on the NRF52840. On later chips (53xx, 54xxx) its an ABP peripherial that can run on a slower clock.

    You can try to interleave your NRF_P2 and NRF_P1 writes - that might use the write buffers more efficient. But the GPIO register access is indeed much slower on the newer chips.

Related