GPIO event shall increment counter without CPU

Hi,

using SDK 3.0.2 and build for the *ns target.

The idea is to put the CPU to sleep and while it is sleeping GPIO events (e.g. button press) shall increment a counter. Once CPU wakes up it gets the counter value and processes it.

Therefore I want to use GPIO and PPI and Timer.

In a first step I just want a "light version", i.e. button press to switch an LED without counter. So one GPIO should be connected via PPI to another GPIO.

The function to do it looks like:

void button_hw_counter_init(void)
{
	nrfx_gpiote_init(NULL, 0);
	gpio_pin_configure_dt(&debug_led, GPIO_OUTPUT_INACTIVE);
	// Use the correct struct for input config
	nrfx_gpiote_input_pin_config_t gpiote_in_cfg = {
		.p_pull_config = &pullup
	};
	nrfx_err_t res = nrfx_gpiote_input_configure(NULL, button3.pin, &gpiote_in_cfg);
	if (res != NRFX_SUCCESS) {
		LOG_ERR("nrfx_gpiote_input_configure failed: %d", res);
	}
// 	// nrfx_gpiote_event_enable(BUTTON3_GPIOTE_CH, true); // Remove if not available
	nrf_gpio_cfg_output(debug_led.pin);
	nrf_gpio_pin_clear(debug_led.pin);
	nrf_gpiote_task_configure(NRF_GPIOTE, BUTTON3_GPIOTE_CH + 1, debug_led.pin,
							  NRF_GPIOTE_POLARITY_LOTOHI, NRF_GPIOTE_INITIAL_VALUE_LOW);
	nrf_gpiote_task_enable(NRF_GPIOTE, BUTTON3_GPIOTE_CH + 1);
	uint8_t dppi_ch = BUTTON3_DPPI_CH;
#if defined(DPPI_PRESENT)
	nrfx_dppi_channel_enable(NULL, dppi_ch);
#else
	nrfx_ppi_channel_enable(dppi_ch);
#endif
	uint32_t gpiote_evt_addr = nrfx_gpiote_in_event_address_get(NULL, BUTTON3_GPIOTE_CH);
	uint32_t gpiote_task_addr = nrfx_gpiote_out_task_address_get(NULL, BUTTON3_GPIOTE_CH + 1);
#if defined(DPPI_PRESENT)
	nrfx_gppi_channel_endpoints_setup(dppi_ch, gpiote_evt_addr, gpiote_task_addr);
#else
	nrfx_ppi_channel_endpoint_setup(dppi_ch, gpiote_evt_addr, gpiote_task_addr);
#endif
}

The .config in the output looks like this:

#
# Peripheral Secure mapping
#
# CONFIG_NRF_FPU_SECURE is not set
# CONFIG_NRF_CLOCK_SECURE is not set
# CONFIG_NRF_POWER_SECURE is not set
# CONFIG_NRF_SPIM0_SECURE is not set
# CONFIG_NRF_TWIM0_SECURE is not set
CONFIG_NRF_UARTE0_SECURE=y
# CONFIG_NRF_SPIM1_SECURE is not set
# CONFIG_NRF_TWIM1_SECURE is not set
# CONFIG_NRF_UARTE1_SECURE is not set
# CONFIG_NRF_SPIM2_SECURE is not set
# CONFIG_NRF_TWIM2_SECURE is not set
# CONFIG_NRF_UARTE2_SECURE is not set
# CONFIG_NRF_SPIM3_SECURE is not set
# CONFIG_NRF_TWIM3_SECURE is not set
# CONFIG_NRF_UARTE3_SECURE is not set
# CONFIG_NRF_SAADC_SECURE is not set
# CONFIG_NRF_TIMER0_SECURE is not set
# CONFIG_NRF_TIMER1_SECURE is not set
# CONFIG_NRF_TIMER2_SECURE is not set
# CONFIG_NRF_RTC0_SECURE is not set
# CONFIG_NRF_RTC1_SECURE is not set
# CONFIG_NRF_DPPI_SECURE is not set
# CONFIG_NRF_WDT0_SECURE is not set
# CONFIG_NRF_EGU0_SECURE is not set
# CONFIG_NRF_EGU1_SECURE is not set
# CONFIG_NRF_EGU2_SECURE is not set
# CONFIG_NRF_EGU3_SECURE is not set
# CONFIG_NRF_EGU4_SECURE is not set
# CONFIG_NRF_EGU5_SECURE is not set
# CONFIG_NRF_PWM0_SECURE is not set
# CONFIG_NRF_PWM1_SECURE is not set
# CONFIG_NRF_PWM2_SECURE is not set
# CONFIG_NRF_PWM3_SECURE is not set
# CONFIG_NRF_PDM_SECURE is not set
# CONFIG_NRF_I2S_SECURE is not set
# CONFIG_NRF_IPC_SECURE is not set
# CONFIG_NRF_NVMC_SECURE is not set
# CONFIG_NRF_GPIO0_SECURE is not set
# CONFIG_NRF_GPIOTE0_SECURE is not set
CONFIG_NRF_GPIO0_PIN_MASK_SECURE=0x00000000
CONFIG_NRF_DPPI_CHANNEL_MASK_SECURE=0x00000000
CONFIG_NRF_VMC_SECURE=y
# end of Peripheral Secure mapping

When I boot the previously working software prints:

All pins have been configured as non-secure
Booting TF-M v2.1.1-ncs4-2
[Sec Thread] Secure image initializing!
FATAL ERROR: SecureFault
FATAL ERROR: HardFault

Tried to play with configs like:

#CONFIG_NRFX_GPIOTE=y
#CONFIG_NRFX_TIMER2=y
#CONFIG_NRFX_DPPI=y
CONFIG_NRFX_GPPI=y

# CONFIG_TFM_SECURE_UART=n
# CONFIG_TFM_SECURE_UART_SHARE_INSTANCE=y

CONFIG_NRF_GPIO0_SECURE=n
CONFIG_NRF_GPIOTE0_SECURE=n
CONFIG_NRF_DPPI_SECURE=n

CONFIG_NRF_GPIO1_SECURE=n

# CONFIG_NRF_UARTE0_SECURE=n
# CONFIG_TFM_SECURE_UART=n

CONFIG_NRF_GPIO0_PIN_MASK_SECURE=0x00000000
CONFIG_NRF_DPPI_CHANNEL_MASK_SECURE=0x00000000

# CONFIG_TFM_SECURE_UART=n
#CONFIG_TFM_SECURE_UART_SHARE_INSTANCE=y
# CONFIG_TFM_LOG_LEVEL_SILENCE=y

#CONFIG_BUILD_WITH_TFM=n

but without luck.

Can you give me a very simple example or hint how to solve this?

Parents
  • Hi,

     

    Here's a sample that uses gpiote + timer + dppi to measure a edge:

     Best way to measure time between falling/rising edges (NCS, Zephyr, NRF52840) 

     

    There are also samples in the nrfx folder which could be of interest for you:

    path/to/ncs/modules/hal/nordic/nrfx/samples/src/nrfx_gppi

     

    Since you are seeing a fault condition, I would recommend that you run this sample isolated for testing purposes, for board nrf9160dk/nrf9160 (note the lack of /ns), and see if this fault still occurs. If the fault still occurs, please share the output.

     

    Kind regards,

    Håkon

  • Hi,

    1. For the build without ns I get:

    /ncs/v3.0.2/nrf/lib/at_monitor/at_monitor.c:11:10: fatal error: nrf_modem_at.h: No such file or directory



    2. When I build for ns and comment the function button_hw_counter_init() which i posted above, it boots without error. But obviously I need that function.

    If I shrink the function to

     

    void button_hw_counter_init(void)
    {
    	nrfx_gpiote_init(NULL, 0);
    }


    the behaviour is the same. So it already crashed here. Is GPIOTE already used by TFM and hence not available for me?

    I build upton the pp_modules example.

    3. When I try to build path/to/ncs/modules/hal/nordic/nrfx/samples/src/nrfx_gppi without any modification but just the build config:

    I get:

     

    CMake Error at CMakeLists.txt:11 (GET_DEVICE_CONFIG_FILES):
      GET_DEVICE_CONFIG_FILES Macro invoked with incorrect arguments for macro
      named: GET_DEVICE_CONFIG_FILES


    while

     

    cmake_minimum_required(VERSION 3.20.0)
    
    if(DEFINED CUSTOM_BOILERPLATE)
        include(${CUSTOM_BOILERPLATE})
        return()
    endif()
    
    set(COMMON_PATH ${CMAKE_CURRENT_LIST_DIR}/common)
    include(${COMMON_PATH}/common.cmake)
    
    GET_DEVICE_CONFIG_FILES(${BOARD} boards)
    
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(one_to_one)
    target_sources(app PRIVATE main.c)
    target_include_directories(app PRIVATE common)
    

    If i fix the error by 

    # GET_DEVICE_CONFIG_FILES(${BOARD} boards)

    I can build for nrf9160dk/nrf9160 but not for nrf9160dk/nrf9160/ns:

    /ncs/v3.0.2/modules/hal/nordic/nrfx/drivers/include/nrfx_gpiote.h:183:57: error: 'nrfx_gpiote_0_irq_handler' undeclared (first use in this function); did you mean 'nrfx_timer_0_irq_handler'?
    
    /ncs/v3.0.2/modules/hal/nordic/nrfx/drivers/include/nrfx_gpiote.h:76:33: error: 'NRFX_GPIOTE0_INST_IDX' undeclared (first use in this function); did you mean 'NRFX_TIMER0_INST_IDX'?

Reply
  • Hi,

    1. For the build without ns I get:

    /ncs/v3.0.2/nrf/lib/at_monitor/at_monitor.c:11:10: fatal error: nrf_modem_at.h: No such file or directory



    2. When I build for ns and comment the function button_hw_counter_init() which i posted above, it boots without error. But obviously I need that function.

    If I shrink the function to

     

    void button_hw_counter_init(void)
    {
    	nrfx_gpiote_init(NULL, 0);
    }


    the behaviour is the same. So it already crashed here. Is GPIOTE already used by TFM and hence not available for me?

    I build upton the pp_modules example.

    3. When I try to build path/to/ncs/modules/hal/nordic/nrfx/samples/src/nrfx_gppi without any modification but just the build config:

    I get:

     

    CMake Error at CMakeLists.txt:11 (GET_DEVICE_CONFIG_FILES):
      GET_DEVICE_CONFIG_FILES Macro invoked with incorrect arguments for macro
      named: GET_DEVICE_CONFIG_FILES


    while

     

    cmake_minimum_required(VERSION 3.20.0)
    
    if(DEFINED CUSTOM_BOILERPLATE)
        include(${CUSTOM_BOILERPLATE})
        return()
    endif()
    
    set(COMMON_PATH ${CMAKE_CURRENT_LIST_DIR}/common)
    include(${COMMON_PATH}/common.cmake)
    
    GET_DEVICE_CONFIG_FILES(${BOARD} boards)
    
    find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
    project(one_to_one)
    target_sources(app PRIVATE main.c)
    target_include_directories(app PRIVATE common)
    

    If i fix the error by 

    # GET_DEVICE_CONFIG_FILES(${BOARD} boards)

    I can build for nrf9160dk/nrf9160 but not for nrf9160dk/nrf9160/ns:

    /ncs/v3.0.2/modules/hal/nordic/nrfx/drivers/include/nrfx_gpiote.h:183:57: error: 'nrfx_gpiote_0_irq_handler' undeclared (first use in this function); did you mean 'nrfx_timer_0_irq_handler'?
    
    /ncs/v3.0.2/modules/hal/nordic/nrfx/drivers/include/nrfx_gpiote.h:76:33: error: 'NRFX_GPIOTE0_INST_IDX' undeclared (first use in this function); did you mean 'NRFX_TIMER0_INST_IDX'?

Children
  • Hi,

     

    Could you try to place your logic in a minimal sample, like zephyr/samples/hello_world or similar, then see if the gpiote/ppi/timer logic runs as expected?

    Artnia said:
    When I try to build path/to/ncs/modules/hal/nordic/nrfx/samples/src/nrfx_gppi without any modification but just the build config:

    Inside that folder there are two samples. You could look at both to see which one is closest to your use-case.

     

    Kind regards,

    Håkon

  • 1. As a base for a minimal sample I use /home/art/ncs/v3.0.2/nrf/samples/net/mqtt for nrf9160dk/nrf9160/ns.

    Usually is says on boot:

    *** Booting nRF Connect SDK v2.8.0-a2386bfc8401 ***
    *** Using Zephyr OS v3.7.99-0bc3393fb112 ***
    [00:00:00.395,111] <inf> network: Bringing network interface up and connecting to the network

    First of all it doesn't build:

    - /src/modules/network/network.c:16:30: error: 'CONFIG_MQTT_SAMPLE_NETWORK_LOG_LEVEL' undeclared here (not in a function); did you mean 'CONFIG_MQTT_SAMPLE_ERROR_LOG_LEVEL'?

    - /src/modules/network/network.c:110:17: error: 'CONFIG_MQTT_SAMPLE_NETWORK_THREAD_STACK_SIZE' undeclared here (not in a function); did you mean 'CONFIG_MQTT_SAMPLE_SAMPLER_THREAD_STACK_SIZE'?

    When I replace both with a hard coded value it builds.
    Inside the trigger task I add line 14+15

    static void trigger_task(void)
    {
    #if CONFIG_DK_LIBRARY
    	int err = dk_buttons_init(button_handler);
    
    	if (err) {
    		LOG_ERR("dk_buttons_init, error: %d", err);
    		SEND_FATAL_ERROR();
    		return;
    	}
    #endif /* CONFIG_DK_LIBRARY */
    
    
    	nrfx_gpiote_init(NULL, 0);
    	LOG_INF("GPIOTE initialized");
    
    	while (true) {
    		message_send();
    		k_sleep(K_SECONDS(CONFIG_MQTT_SAMPLE_TRIGGER_TIMEOUT_SECONDS));
    	}
    }

    and the behaviour is that nothing is printed.

    2. If I do the same for hello_world it seems to work:

    int main(void)
    {
    	printf("Hello World! %s\n", CONFIG_BOARD_TARGET);
    
    	nrfx_gpiote_init(NULL, 0);
    
    	printf("GPIOTE initialized successfully.\n");
    
    	return 0;
    }

    Output:

    All pins have been configured as non-secure
    Booting TF-M v2.1.1-ncs4-2
    [Sec Thread] Secure image initializing!
    *** Booting nRF Connect SDK v3.0.2-89ba1294ac9b ***
    *** Using Zephyr OS v4.0.99-f791c49f492c ***
    Hello World! [email protected]/nrf9160/ns
    GPIOTE initialized successfully.

    3. According to https://docs.nordicsemi.com/bundle/ps_nrf9160/page/gpiote.html#d558e286
    which one (GPIOTE0 or GPIOTE1) should I be using in my application if ns/TFM is enabled? And does ns/TFM also use one of them?
    https://docs.nordicsemi.com/bundle/ps_nrf9160/page/dppi.html is also related

  • Hi,

     

    Artnia said:

    First of all it doesn't build:

    - /src/modules/network/network.c:16:30: error: 'CONFIG_MQTT_SAMPLE_NETWORK_LOG_LEVEL' undeclared here (not in a function); did you mean 'CONFIG_MQTT_SAMPLE_ERROR_LOG_LEVEL'?

    - /src/modules/network/network.c:110:17: error: 'CONFIG_MQTT_SAMPLE_NETWORK_THREAD_STACK_SIZE' undeclared here (not in a function); did you mean 'CONFIG_MQTT_SAMPLE_SAMPLER_THREAD_STACK_SIZE'?

    It is hard to say what has happened here, have you done any changes to the project?

    First, try to delete your build folder and regenerate the build.

     

    The API has been changed for nrfx_gpiote_init function. Instead of:

    nrfx_gpiote_init(NULL, 0);

    You need to provide the instance:

    nrfx_gpiote_t const gpiote_inst = NRFX_GPIOTE_INSTANCE(GPIOTE_INST_IDX);
    status = nrfx_gpiote_init(&gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);

     

    Where 0 is for secure, and 1 is for non-secure:

    https://docs.nordicsemi.com/bundle/ps_nrf9160/page/gpiote.html#d558e286

     

    Kind regards,

    Håkon

Related