Use GPIO output Signal as event to trigger a TIMER

Hello,

For my prject I need to tiggrer a timer start using a pin. I'm trying do do it using PPI but it seems that GPOITE can only create events on input pins. If anyone know how to do thaht:

- Use a pin as output

- set that pin to 1

- use thaht signal to trigger a timer start task.

Thanks

Parents
  • A little update, 

    I managed to implement a PPI (Power Point Imaging) function by directly connecting my GPIOTE output to a GPIOTE input to use it as an event trigger. Since I'm doing this to measure detection time, I'm getting about 8µs via software, while on my oscilloscope it's 2µs. My question was whether there's a more direct and faster way to achieve this.

    I've attached my code.

    Thanks

    #include <stdio.h>
    #include <zephyr/kernel.h>
    //#include <zephyr/drivers/gpio.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/comparator.h>
    #include <zephyr/logging/log.h>
    
    #include <nrfx_timer.h>
    #include <hal/nrf_timer.h>
    #include <helpers/nrfx_gppi.h>
    #include <hal/nrf_lpcomp.h>
    #include <nrfx_gpiote.h>
    #include <nrfx_egu.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS 3000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE       DT_ALIAS(led0)
    #define LED1_NODE       DT_ALIAS(led1)
    #define led0_pin		NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(led0), gpios)
    #define led1_pin		NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(led1), gpios)
    #define LOG_MODULE_NAME app
    #define TIMER_INST_IDX  NRF_TIMER22
    #define GPIOTE_INST_IDX NRF_GPIOTE30
    #define EGU_INST_IDX 	NRF_EGU20
    #define TIMER22_TICK_NS 62.5f
    #define TICKS_US_DIV    1000u
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    /*
     * A build error on this line means your board is unsupported.
     * See the sample documentation for information on how to fix this.
     */
    static const struct device *comp_dev = DEVICE_DT_GET(DT_NODELABEL(comp));
    #define time_trigger_pin_nbr NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), time_trigger_gpios)
    
    #define GPIOTE_INST	NRF_DT_GPIOTE_INST(DT_PATH(zephyr_user), comp_trigger_gpios)
    #define GPIOTE_NODE	DT_NODELABEL(_CONCAT(gpiote, GPIOTE_INST))
    #define input_trigger_pin_nbr NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), input_event_gpios)
    static const uint32_t comp_trigger_pin_nbr = NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), comp_trigger_gpios);
    
    nrfx_gpiote_t gpiote_inst = NRFX_GPIOTE_INSTANCE(NRF_GPIOTE_INST_GET(GPIOTE_INST));//NRFX_GPIOTE_INSTANCE(GPIOTE_INST_IDX);
    nrfx_timer_t timer_inst = NRFX_TIMER_INSTANCE(TIMER_INST_IDX);
    
    static volatile uint32_t T_rise = 0xFFFFFFFF;
    static volatile uint32_t T_fall = 0xFFFFFFFF;
    
    static const uint8_t DPPI_CH_UP;
    static const uint8_t DPPI_CH_DOWN;
    bool upEventCheck = true;
    
    static void lpcomp_callback(const struct device *dev, void *user_data)
    {
    	NRF_LPCOMP_Type *comp = NRF_LPCOMP;
    	nrfx_gpiote_out_clear(&gpiote_inst,time_trigger_pin_nbr);
    	uint32_t up, down = 0;
    	if(upEventCheck== true){
    		upEventCheck= false;
    		// up  = nrf_timer_cc_get(timer_inst.p_reg, 0);
    		up = nrfx_timer_capture_get(&timer_inst, NRF_TIMER_CC_CHANNEL0);
    		LOG_INF("Timer value get on event UP as %.1f us", (double)((up * TIMER22_TICK_NS) / TICKS_US_DIV));
    		if (up != 0 && T_rise == 0xFFFFFFFF) {
    			T_rise = up;
    			LOG_INF("UP event: %.1f us", (double)(up * TIMER22_TICK_NS) / TICKS_US_DIV);
    		}
    	} 
    	else {
    		down = nrf_timer_cc_get(timer_inst.p_reg, 1);
    		upEventCheck = true;
    		LOG_INF("Timer value get on event DOWN as %.1f us", (double)((up * TIMER22_TICK_NS) / TICKS_US_DIV));		
    		if (down != 0 && T_fall == 0xFFFFFFFF) {
    			T_fall = down;
    			LOG_INF("DOWN event: %u us", down);
    		}
    	}
    
    	nrf_timer_task_trigger(timer_inst.p_reg, NRF_TIMER_TASK_CLEAR);
    	nrf_timer_task_trigger(timer_inst.p_reg, NRF_TIMER_TASK_STOP);
    
    	nrfx_gpiote_out_toggle(&gpiote_inst,led0_pin);
    	LOG_INF("lp_comp event");
    }
    
    static void dppi_route_init(void)
    {
    	/* PUBLISH : LPCOMP UP/DOWN -> 2 canaux DPPI */
    	nrf_lpcomp_publish_set(NRF_LPCOMP, NRF_LPCOMP_EVENT_UP, DPPI_CH_UP);
    	nrf_lpcomp_publish_set(NRF_LPCOMP, NRF_LPCOMP_EVENT_DOWN, DPPI_CH_DOWN);
    
    	/* SUBSCRIBE : TIMER CAPTURE[0]/[1] <- DPPI */
    	nrf_timer_subscribe_set(timer_inst.p_reg, NRF_TIMER_TASK_CAPTURE0, DPPI_CH_UP);
    	nrf_timer_subscribe_set(timer_inst.p_reg, NRF_TIMER_TASK_CAPTURE1, DPPI_CH_DOWN);
    
    	/* Enable canaux DPPI */
    	NRF_DPPIC20->CHENSET = BIT(DPPI_CH_UP) | BIT(DPPI_CH_DOWN);
    
    	LOG_INF("DPPI: LPCOMP UP->CAP0(CH%d) / DOWN->CAP1(CH%d)", DPPI_CH_UP, DPPI_CH_DOWN);
    }
    
    static void gpiote_init_edge_input(void)
    {
    	nrfx_err_t status;
    	uint8_t in_channel, out_channel;
    	
    	// init driver instance
    	status = nrfx_gpiote_init(&gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
    	if (status != NRFX_SUCCESS && status != NRFX_ERROR_ALREADY) {
    		// handle error
    	}
    
    	LOG_INF("GPIOTE status: %s",
    		nrfx_gpiote_init_check(&gpiote_inst) ? "initialized" : "not initialized");
    
    	status = nrfx_gpiote_channel_alloc(&gpiote_inst, &out_channel);
    	if (status != NRFX_SUCCESS) {
    		// handle error
    	}
    
    	static const nrf_gpio_pin_pull_t pull_config = NRF_GPIO_PIN_PULLUP;
    	nrfx_gpiote_trigger_config_t trigger_config = {
    		.trigger = NRFX_GPIOTE_TRIGGER_TOGGLE,
    		.p_in_channel = &in_channel,
    	};
    	static const nrfx_gpiote_handler_config_t handler_config = {
    		.handler = NULL,
    	};
    	nrfx_gpiote_input_pin_config_t input_config = {
    		.p_pull_config = &pull_config,
    		.p_trigger_config = &trigger_config,
    		.p_handler_config = &handler_config
    	};
    
    	status = nrfx_gpiote_input_configure(&gpiote_inst,input_trigger_pin_nbr, &input_config);
    
    	static const nrf_gpio_pin_pull_t pull_cfg = NRF_GPIO_PIN_PULLUP;
    	nrfx_gpiote_trigger_config_t trig_cfg = {
    		.trigger = NRFX_GPIOTE_TRIGGER_LOTOHI,
    		.p_in_channel = &out_channel,
    	};
    	static const nrfx_gpiote_handler_config_t handler_cfg = {
    		.handler = NULL,
    		.p_context = NULL,
    	};
    	
    	nrfx_gpiote_output_config_t output_cfg = NRFX_GPIOTE_DEFAULT_OUTPUT_CONFIG;
    	const nrfx_gpiote_task_config_t task_config = {
    		.task_ch = out_channel,
    		.polarity = NRF_GPIOTE_POLARITY_TOGGLE,
    		.init_val = 0,
    	};
    
    	status = nrfx_gpiote_output_configure(&gpiote_inst, comp_trigger_pin_nbr, &output_cfg, &task_config);
    	if (status != NRFX_SUCCESS) {
    		// handle error
    	}
    	
    	status = nrfx_gpiote_output_configure(&gpiote_inst, time_trigger_pin_nbr, &output_cfg, NULL);
    	status = nrfx_gpiote_output_configure(&gpiote_inst, led0_pin, &output_cfg, NULL);
    	status = nrfx_gpiote_output_configure(&gpiote_inst, led1_pin, &output_cfg, NULL);
    
    	nrfx_gpiote_trigger_enable(&gpiote_inst, input_trigger_pin_nbr, true);
    	nrfx_gpiote_out_task_enable(&gpiote_inst, comp_trigger_pin_nbr);
    }
    
    static void ddpi_init(void)
    {
    	int status;
    	nrfx_gppi_handle_t gppi_handle_up, gppi_handle_down, gppi_comp_trigger;
    
    	uint32_t evt_addr_up = nrf_lpcomp_event_address_get(NRF_LPCOMP, NRF_LPCOMP_EVENT_UP);
    	uint32_t task_addr_CC0 =
    		nrfx_timer_capture_task_address_get(&timer_inst, NRF_TIMER_CC_CHANNEL0);
    
    	status = nrfx_gppi_conn_alloc(evt_addr_up, task_addr_CC0, &gppi_handle_up);
    	NRFX_ASSERT(status == NRFX_SUCCESS);
    
    	// Enable the connection using the handle
    	nrfx_gppi_conn_enable(gppi_handle_up);
    
    
    	uint32_t evt_addr_down = nrf_lpcomp_event_address_get(NRF_LPCOMP, NRF_LPCOMP_EVENT_DOWN);
    	uint32_t task_addr_CC1 = nrfx_timer_capture_task_address_get(&timer_inst, NRF_TIMER_CC_CHANNEL1);
    
    	status = nrfx_gppi_conn_alloc(evt_addr_down, task_addr_CC1, &gppi_handle_down);
    	NRFX_ASSERT(status == NRFX_SUCCESS);
    
    	// Enable the connection using the handle
    	nrfx_gppi_conn_enable(gppi_handle_down);
    
    	uint32_t evt_addr_start = nrfx_gpiote_in_event_address_get(&gpiote_inst, input_trigger_pin_nbr);
    	uint32_t task_addr_start = nrfx_timer_task_address_get(&timer_inst, NRF_TIMER_TASK_START);
    
    	status = nrfx_gppi_conn_alloc(evt_addr_start, task_addr_start, &gppi_comp_trigger);
    	NRFX_ASSERT(status == NRFX_SUCCESS);
    	
    	// Enable the connection using the handle
    	nrfx_gppi_conn_enable(gppi_comp_trigger);
    
    	LOG_INF("ddpi_init Done ");
    }
    
    static void initTimer()
    {
    	uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer_inst.p_reg);
    	nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(NRF_TIMER_BASE_FREQUENCY_16MHZ);
    	config.bit_width = NRF_TIMER_BIT_WIDTH_32;
    	int status = nrfx_timer_init(&timer_inst, &config, NULL);
    	if (status != NRFX_SUCCESS) {
    		return;
    	} else {
    		nrfx_timer_clear(&timer_inst);
    		return;
    	}
    }
    
    int main(void)
    {
    	int ret;
    	bool led_state = true;
    
    	initTimer();
    	gpiote_init_edge_input();
    	ddpi_init();
    
    	if (!device_is_ready(comp_dev)) {
    		LOG_ERR("%s is not ready", comp_dev->name);
    		return 0;
    	}
    	ret = comparator_set_trigger_callback(comp_dev, lpcomp_callback, NULL);
    	if (ret) {
    		LOG_ERR("comparator_set_trigger_callback() failed. (err: %d)", ret);
    		return 0;
    	}
    
    	ret = comparator_set_trigger(comp_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
    	if (ret) {
    		LOG_ERR("comparator_set_trigger() failed. (err: %d)", ret);
    		return 0;
    	}
    
    	LOG_INF("Starup ok, Entering While loop");
    	while (1) {
    		// nrfx_timer_enable(&timer_inst);
    		T_rise = 0xFFFFFFFF;
    		T_fall = 0xFFFFFFFF;
    
    		LOG_INF("Triggering SET TASK");
    		nrfx_gpiote_out_task_trigger(&gpiote_inst,comp_trigger_pin_nbr);
    		
    		LOG_INF("Triggering TIMER PIN");
    		nrfx_gpiote_out_set(&gpiote_inst,time_trigger_pin_nbr);
    		
    		LOG_INF("Toggle LED1");
    		nrfx_gpiote_out_toggle(&gpiote_inst,led1_pin);
    		if (ret < 0) {
    			return 0;
    		}
    
    		if (T_rise != 0xFFFFFFFF && T_fall != 0xFFFFFFFF) {
    			int32_t dt = (int32_t)T_fall - (int32_t)T_rise;
    			LOG_INF("Δt = %d us", dt);
    
    			/* reset pour nouvelle mesure */
    			T_rise = T_fall = 0xFFFFFFFF;
    		}
    
    		LOG_INF("SLEEP\n\n");
    		k_msleep(SLEEP_TIME_MS);
    	}
    	return 0;
    }

Reply
  • A little update, 

    I managed to implement a PPI (Power Point Imaging) function by directly connecting my GPIOTE output to a GPIOTE input to use it as an event trigger. Since I'm doing this to measure detection time, I'm getting about 8µs via software, while on my oscilloscope it's 2µs. My question was whether there's a more direct and faster way to achieve this.

    I've attached my code.

    Thanks

    #include <stdio.h>
    #include <zephyr/kernel.h>
    //#include <zephyr/drivers/gpio.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/comparator.h>
    #include <zephyr/logging/log.h>
    
    #include <nrfx_timer.h>
    #include <hal/nrf_timer.h>
    #include <helpers/nrfx_gppi.h>
    #include <hal/nrf_lpcomp.h>
    #include <nrfx_gpiote.h>
    #include <nrfx_egu.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS 3000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE       DT_ALIAS(led0)
    #define LED1_NODE       DT_ALIAS(led1)
    #define led0_pin		NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(led0), gpios)
    #define led1_pin		NRF_DT_GPIOS_TO_PSEL(DT_ALIAS(led1), gpios)
    #define LOG_MODULE_NAME app
    #define TIMER_INST_IDX  NRF_TIMER22
    #define GPIOTE_INST_IDX NRF_GPIOTE30
    #define EGU_INST_IDX 	NRF_EGU20
    #define TIMER22_TICK_NS 62.5f
    #define TICKS_US_DIV    1000u
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    /*
     * A build error on this line means your board is unsupported.
     * See the sample documentation for information on how to fix this.
     */
    static const struct device *comp_dev = DEVICE_DT_GET(DT_NODELABEL(comp));
    #define time_trigger_pin_nbr NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), time_trigger_gpios)
    
    #define GPIOTE_INST	NRF_DT_GPIOTE_INST(DT_PATH(zephyr_user), comp_trigger_gpios)
    #define GPIOTE_NODE	DT_NODELABEL(_CONCAT(gpiote, GPIOTE_INST))
    #define input_trigger_pin_nbr NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), input_event_gpios)
    static const uint32_t comp_trigger_pin_nbr = NRF_DT_GPIOS_TO_PSEL(DT_PATH(zephyr_user), comp_trigger_gpios);
    
    nrfx_gpiote_t gpiote_inst = NRFX_GPIOTE_INSTANCE(NRF_GPIOTE_INST_GET(GPIOTE_INST));//NRFX_GPIOTE_INSTANCE(GPIOTE_INST_IDX);
    nrfx_timer_t timer_inst = NRFX_TIMER_INSTANCE(TIMER_INST_IDX);
    
    static volatile uint32_t T_rise = 0xFFFFFFFF;
    static volatile uint32_t T_fall = 0xFFFFFFFF;
    
    static const uint8_t DPPI_CH_UP;
    static const uint8_t DPPI_CH_DOWN;
    bool upEventCheck = true;
    
    static void lpcomp_callback(const struct device *dev, void *user_data)
    {
    	NRF_LPCOMP_Type *comp = NRF_LPCOMP;
    	nrfx_gpiote_out_clear(&gpiote_inst,time_trigger_pin_nbr);
    	uint32_t up, down = 0;
    	if(upEventCheck== true){
    		upEventCheck= false;
    		// up  = nrf_timer_cc_get(timer_inst.p_reg, 0);
    		up = nrfx_timer_capture_get(&timer_inst, NRF_TIMER_CC_CHANNEL0);
    		LOG_INF("Timer value get on event UP as %.1f us", (double)((up * TIMER22_TICK_NS) / TICKS_US_DIV));
    		if (up != 0 && T_rise == 0xFFFFFFFF) {
    			T_rise = up;
    			LOG_INF("UP event: %.1f us", (double)(up * TIMER22_TICK_NS) / TICKS_US_DIV);
    		}
    	} 
    	else {
    		down = nrf_timer_cc_get(timer_inst.p_reg, 1);
    		upEventCheck = true;
    		LOG_INF("Timer value get on event DOWN as %.1f us", (double)((up * TIMER22_TICK_NS) / TICKS_US_DIV));		
    		if (down != 0 && T_fall == 0xFFFFFFFF) {
    			T_fall = down;
    			LOG_INF("DOWN event: %u us", down);
    		}
    	}
    
    	nrf_timer_task_trigger(timer_inst.p_reg, NRF_TIMER_TASK_CLEAR);
    	nrf_timer_task_trigger(timer_inst.p_reg, NRF_TIMER_TASK_STOP);
    
    	nrfx_gpiote_out_toggle(&gpiote_inst,led0_pin);
    	LOG_INF("lp_comp event");
    }
    
    static void dppi_route_init(void)
    {
    	/* PUBLISH : LPCOMP UP/DOWN -> 2 canaux DPPI */
    	nrf_lpcomp_publish_set(NRF_LPCOMP, NRF_LPCOMP_EVENT_UP, DPPI_CH_UP);
    	nrf_lpcomp_publish_set(NRF_LPCOMP, NRF_LPCOMP_EVENT_DOWN, DPPI_CH_DOWN);
    
    	/* SUBSCRIBE : TIMER CAPTURE[0]/[1] <- DPPI */
    	nrf_timer_subscribe_set(timer_inst.p_reg, NRF_TIMER_TASK_CAPTURE0, DPPI_CH_UP);
    	nrf_timer_subscribe_set(timer_inst.p_reg, NRF_TIMER_TASK_CAPTURE1, DPPI_CH_DOWN);
    
    	/* Enable canaux DPPI */
    	NRF_DPPIC20->CHENSET = BIT(DPPI_CH_UP) | BIT(DPPI_CH_DOWN);
    
    	LOG_INF("DPPI: LPCOMP UP->CAP0(CH%d) / DOWN->CAP1(CH%d)", DPPI_CH_UP, DPPI_CH_DOWN);
    }
    
    static void gpiote_init_edge_input(void)
    {
    	nrfx_err_t status;
    	uint8_t in_channel, out_channel;
    	
    	// init driver instance
    	status = nrfx_gpiote_init(&gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
    	if (status != NRFX_SUCCESS && status != NRFX_ERROR_ALREADY) {
    		// handle error
    	}
    
    	LOG_INF("GPIOTE status: %s",
    		nrfx_gpiote_init_check(&gpiote_inst) ? "initialized" : "not initialized");
    
    	status = nrfx_gpiote_channel_alloc(&gpiote_inst, &out_channel);
    	if (status != NRFX_SUCCESS) {
    		// handle error
    	}
    
    	static const nrf_gpio_pin_pull_t pull_config = NRF_GPIO_PIN_PULLUP;
    	nrfx_gpiote_trigger_config_t trigger_config = {
    		.trigger = NRFX_GPIOTE_TRIGGER_TOGGLE,
    		.p_in_channel = &in_channel,
    	};
    	static const nrfx_gpiote_handler_config_t handler_config = {
    		.handler = NULL,
    	};
    	nrfx_gpiote_input_pin_config_t input_config = {
    		.p_pull_config = &pull_config,
    		.p_trigger_config = &trigger_config,
    		.p_handler_config = &handler_config
    	};
    
    	status = nrfx_gpiote_input_configure(&gpiote_inst,input_trigger_pin_nbr, &input_config);
    
    	static const nrf_gpio_pin_pull_t pull_cfg = NRF_GPIO_PIN_PULLUP;
    	nrfx_gpiote_trigger_config_t trig_cfg = {
    		.trigger = NRFX_GPIOTE_TRIGGER_LOTOHI,
    		.p_in_channel = &out_channel,
    	};
    	static const nrfx_gpiote_handler_config_t handler_cfg = {
    		.handler = NULL,
    		.p_context = NULL,
    	};
    	
    	nrfx_gpiote_output_config_t output_cfg = NRFX_GPIOTE_DEFAULT_OUTPUT_CONFIG;
    	const nrfx_gpiote_task_config_t task_config = {
    		.task_ch = out_channel,
    		.polarity = NRF_GPIOTE_POLARITY_TOGGLE,
    		.init_val = 0,
    	};
    
    	status = nrfx_gpiote_output_configure(&gpiote_inst, comp_trigger_pin_nbr, &output_cfg, &task_config);
    	if (status != NRFX_SUCCESS) {
    		// handle error
    	}
    	
    	status = nrfx_gpiote_output_configure(&gpiote_inst, time_trigger_pin_nbr, &output_cfg, NULL);
    	status = nrfx_gpiote_output_configure(&gpiote_inst, led0_pin, &output_cfg, NULL);
    	status = nrfx_gpiote_output_configure(&gpiote_inst, led1_pin, &output_cfg, NULL);
    
    	nrfx_gpiote_trigger_enable(&gpiote_inst, input_trigger_pin_nbr, true);
    	nrfx_gpiote_out_task_enable(&gpiote_inst, comp_trigger_pin_nbr);
    }
    
    static void ddpi_init(void)
    {
    	int status;
    	nrfx_gppi_handle_t gppi_handle_up, gppi_handle_down, gppi_comp_trigger;
    
    	uint32_t evt_addr_up = nrf_lpcomp_event_address_get(NRF_LPCOMP, NRF_LPCOMP_EVENT_UP);
    	uint32_t task_addr_CC0 =
    		nrfx_timer_capture_task_address_get(&timer_inst, NRF_TIMER_CC_CHANNEL0);
    
    	status = nrfx_gppi_conn_alloc(evt_addr_up, task_addr_CC0, &gppi_handle_up);
    	NRFX_ASSERT(status == NRFX_SUCCESS);
    
    	// Enable the connection using the handle
    	nrfx_gppi_conn_enable(gppi_handle_up);
    
    
    	uint32_t evt_addr_down = nrf_lpcomp_event_address_get(NRF_LPCOMP, NRF_LPCOMP_EVENT_DOWN);
    	uint32_t task_addr_CC1 = nrfx_timer_capture_task_address_get(&timer_inst, NRF_TIMER_CC_CHANNEL1);
    
    	status = nrfx_gppi_conn_alloc(evt_addr_down, task_addr_CC1, &gppi_handle_down);
    	NRFX_ASSERT(status == NRFX_SUCCESS);
    
    	// Enable the connection using the handle
    	nrfx_gppi_conn_enable(gppi_handle_down);
    
    	uint32_t evt_addr_start = nrfx_gpiote_in_event_address_get(&gpiote_inst, input_trigger_pin_nbr);
    	uint32_t task_addr_start = nrfx_timer_task_address_get(&timer_inst, NRF_TIMER_TASK_START);
    
    	status = nrfx_gppi_conn_alloc(evt_addr_start, task_addr_start, &gppi_comp_trigger);
    	NRFX_ASSERT(status == NRFX_SUCCESS);
    	
    	// Enable the connection using the handle
    	nrfx_gppi_conn_enable(gppi_comp_trigger);
    
    	LOG_INF("ddpi_init Done ");
    }
    
    static void initTimer()
    {
    	uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer_inst.p_reg);
    	nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(NRF_TIMER_BASE_FREQUENCY_16MHZ);
    	config.bit_width = NRF_TIMER_BIT_WIDTH_32;
    	int status = nrfx_timer_init(&timer_inst, &config, NULL);
    	if (status != NRFX_SUCCESS) {
    		return;
    	} else {
    		nrfx_timer_clear(&timer_inst);
    		return;
    	}
    }
    
    int main(void)
    {
    	int ret;
    	bool led_state = true;
    
    	initTimer();
    	gpiote_init_edge_input();
    	ddpi_init();
    
    	if (!device_is_ready(comp_dev)) {
    		LOG_ERR("%s is not ready", comp_dev->name);
    		return 0;
    	}
    	ret = comparator_set_trigger_callback(comp_dev, lpcomp_callback, NULL);
    	if (ret) {
    		LOG_ERR("comparator_set_trigger_callback() failed. (err: %d)", ret);
    		return 0;
    	}
    
    	ret = comparator_set_trigger(comp_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
    	if (ret) {
    		LOG_ERR("comparator_set_trigger() failed. (err: %d)", ret);
    		return 0;
    	}
    
    	LOG_INF("Starup ok, Entering While loop");
    	while (1) {
    		// nrfx_timer_enable(&timer_inst);
    		T_rise = 0xFFFFFFFF;
    		T_fall = 0xFFFFFFFF;
    
    		LOG_INF("Triggering SET TASK");
    		nrfx_gpiote_out_task_trigger(&gpiote_inst,comp_trigger_pin_nbr);
    		
    		LOG_INF("Triggering TIMER PIN");
    		nrfx_gpiote_out_set(&gpiote_inst,time_trigger_pin_nbr);
    		
    		LOG_INF("Toggle LED1");
    		nrfx_gpiote_out_toggle(&gpiote_inst,led1_pin);
    		if (ret < 0) {
    			return 0;
    		}
    
    		if (T_rise != 0xFFFFFFFF && T_fall != 0xFFFFFFFF) {
    			int32_t dt = (int32_t)T_fall - (int32_t)T_rise;
    			LOG_INF("Δt = %d us", dt);
    
    			/* reset pour nouvelle mesure */
    			T_rise = T_fall = 0xFFFFFFFF;
    		}
    
    		LOG_INF("SLEEP\n\n");
    		k_msleep(SLEEP_TIME_MS);
    	}
    	return 0;
    }

Children
  • Hi,

    S MOUNZEO said:
    I managed to implement a PPI (Power Point Imaging) function by directly connecting my GPIOTE output to a GPIOTE input to use it as an event trigger.

    I'll assume you are referring to the Programmable Peripheral Interconnect.

    For my prject I need to tiggrer a timer start using a pin. I'm trying do do it using PPI but it seems that GPOITE can only create events on input pins. If anyone know how to do thaht:

    So I believe you can only start a timer from a pin you've set as an input, if we are strictly talking about SW limitations here. If you have set it as an output, I wouldn't really think of this as a problem though, because it is the MCU in question that has pulled this pin high or low - you can just start this timer from the same task you've used to set the pin. PPI wouldn't be necessary.

    I don't think you'd need a pin to start this event either. What did you need to time?

    Regards,

    Elfving

  • Hello,

    What I'd like to measure is the charging time of a capacitor. Activating the pin allows me to initiate the charging process, and I should therefore simultaneously start a timer that stops when a signal is received on another pin configured as an input.

  • I see. Then starting a timer with PPI sounds like the way to go. There have been some cases about similar things here and here that might help out. Let me know if you're still stuck, and I'll try to make you something.

    Regards,

    Elfving

Related