<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Use GPIO output Signal as event to trigger a TIMER</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/127354/use-gpio-output-signal-as-event-to-trigger-a-timer</link><description>Hello, 
 
 For my prject I need to tiggrer a timer start using a pin. I&amp;#39;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</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 18 Mar 2026 14:05:26 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/127354/use-gpio-output-signal-as-event-to-trigger-a-timer" /><item><title>RE: Use GPIO output Signal as event to trigger a TIMER</title><link>https://devzone.nordicsemi.com/thread/563580?ContentTypeID=1</link><pubDate>Wed, 18 Mar 2026 14:05:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:cfae13a7-2f40-4d63-b7cd-ce3a271318c3</guid><dc:creator>Elfving</dc:creator><description>&lt;p&gt;I see. Then starting a timer with PPI sounds like the way to go.&amp;nbsp;There have been some cases about similar things &lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/126443/how-do-i-set-up-gppi-dppi-with-the-new-nrfx-4-0-1-drivers"&gt;here &lt;/a&gt;and &lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/13364/how-to-synchronize-pwm-with-external-event"&gt;here &lt;/a&gt;that might help out. Let me know if you&amp;#39;re still stuck, and I&amp;#39;ll try to make you something.&lt;/p&gt;
&lt;p&gt;Regards,&lt;/p&gt;
&lt;p&gt;Elfving&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Use GPIO output Signal as event to trigger a TIMER</title><link>https://devzone.nordicsemi.com/thread/563306?ContentTypeID=1</link><pubDate>Mon, 16 Mar 2026 10:25:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3ae74287-539e-4787-8dd6-4fdc8a4981fe</guid><dc:creator>S MOUNZEO</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;What I&amp;#39;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.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Use GPIO output Signal as event to trigger a TIMER</title><link>https://devzone.nordicsemi.com/thread/563048?ContentTypeID=1</link><pubDate>Wed, 11 Mar 2026 15:03:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6f77d877-dcc3-4bb0-a43d-a13c9e005667</guid><dc:creator>Elfving</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="S MOUNZEO"]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.[/quote]
&lt;p&gt;I&amp;#39;ll assume you are referring to the&amp;nbsp;&lt;a href="https://docs.nordicsemi.com/bundle/ps_nrf52840/page/ppi.html"&gt;&lt;span&gt;Programmable Peripheral Interconnect.&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
[quote user=""]&lt;p&gt;For my prject I need to tiggrer a timer start using a pin. I&amp;#39;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:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;[/quote]
&lt;p&gt;&lt;span&gt;&lt;/span&gt;So I believe you can only start a timer from a pin you&amp;#39;ve set as an input, if we are strictly talking about SW limitations here. If you have set it as an output, I wouldn&amp;#39;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&amp;nbsp;start this timer from the same task you&amp;#39;ve used to set the pin. PPI wouldn&amp;#39;t be necessary.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t think you&amp;#39;d need a pin to start this event either. What did you need to time?&lt;/p&gt;
&lt;p&gt;Regards,&lt;/p&gt;
&lt;p&gt;Elfving&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Use GPIO output Signal as event to trigger a TIMER</title><link>https://devzone.nordicsemi.com/thread/562932?ContentTypeID=1</link><pubDate>Tue, 10 Mar 2026 14:31:11 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fdac3aec-58e4-4fe5-8b8f-be999d5a0f01</guid><dc:creator>S MOUNZEO</dc:creator><description>&lt;p&gt;A little update,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;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&amp;#39;m doing this to measure detection time, I&amp;#39;m getting about 8&amp;micro;s via software, while on my oscilloscope it&amp;#39;s 2&amp;micro;s. My question was whether there&amp;#39;s a more direct and faster way to achieve this.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve attached my code.&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;zephyr/kernel.h&amp;gt;
//#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;lt;zephyr/device.h&amp;gt;
#include &amp;lt;zephyr/drivers/comparator.h&amp;gt;
#include &amp;lt;zephyr/logging/log.h&amp;gt;

#include &amp;lt;nrfx_timer.h&amp;gt;
#include &amp;lt;hal/nrf_timer.h&amp;gt;
#include &amp;lt;helpers/nrfx_gppi.h&amp;gt;
#include &amp;lt;hal/nrf_lpcomp.h&amp;gt;
#include &amp;lt;nrfx_gpiote.h&amp;gt;
#include &amp;lt;nrfx_egu.h&amp;gt;

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 3000

/* The devicetree node identifier for the &amp;quot;led0&amp;quot; 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(&amp;amp;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(&amp;amp;timer_inst, NRF_TIMER_CC_CHANNEL0);
		LOG_INF(&amp;quot;Timer value get on event UP as %.1f us&amp;quot;, (double)((up * TIMER22_TICK_NS) / TICKS_US_DIV));
		if (up != 0 &amp;amp;&amp;amp; T_rise == 0xFFFFFFFF) {
			T_rise = up;
			LOG_INF(&amp;quot;UP event: %.1f us&amp;quot;, (double)(up * TIMER22_TICK_NS) / TICKS_US_DIV);
		}
	} 
	else {
		down = nrf_timer_cc_get(timer_inst.p_reg, 1);
		upEventCheck = true;
		LOG_INF(&amp;quot;Timer value get on event DOWN as %.1f us&amp;quot;, (double)((up * TIMER22_TICK_NS) / TICKS_US_DIV));		
		if (down != 0 &amp;amp;&amp;amp; T_fall == 0xFFFFFFFF) {
			T_fall = down;
			LOG_INF(&amp;quot;DOWN event: %u us&amp;quot;, 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(&amp;amp;gpiote_inst,led0_pin);
	LOG_INF(&amp;quot;lp_comp event&amp;quot;);
}

static void dppi_route_init(void)
{
	/* PUBLISH : LPCOMP UP/DOWN -&amp;gt; 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] &amp;lt;- 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-&amp;gt;CHENSET = BIT(DPPI_CH_UP) | BIT(DPPI_CH_DOWN);

	LOG_INF(&amp;quot;DPPI: LPCOMP UP-&amp;gt;CAP0(CH%d) / DOWN-&amp;gt;CAP1(CH%d)&amp;quot;, 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(&amp;amp;gpiote_inst, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
	if (status != NRFX_SUCCESS &amp;amp;&amp;amp; status != NRFX_ERROR_ALREADY) {
		// handle error
	}

	LOG_INF(&amp;quot;GPIOTE status: %s&amp;quot;,
		nrfx_gpiote_init_check(&amp;amp;gpiote_inst) ? &amp;quot;initialized&amp;quot; : &amp;quot;not initialized&amp;quot;);

	status = nrfx_gpiote_channel_alloc(&amp;amp;gpiote_inst, &amp;amp;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 = &amp;amp;in_channel,
	};
	static const nrfx_gpiote_handler_config_t handler_config = {
		.handler = NULL,
	};
	nrfx_gpiote_input_pin_config_t input_config = {
		.p_pull_config = &amp;amp;pull_config,
		.p_trigger_config = &amp;amp;trigger_config,
		.p_handler_config = &amp;amp;handler_config
	};

	status = nrfx_gpiote_input_configure(&amp;amp;gpiote_inst,input_trigger_pin_nbr, &amp;amp;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 = &amp;amp;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(&amp;amp;gpiote_inst, comp_trigger_pin_nbr, &amp;amp;output_cfg, &amp;amp;task_config);
	if (status != NRFX_SUCCESS) {
		// handle error
	}
	
	status = nrfx_gpiote_output_configure(&amp;amp;gpiote_inst, time_trigger_pin_nbr, &amp;amp;output_cfg, NULL);
	status = nrfx_gpiote_output_configure(&amp;amp;gpiote_inst, led0_pin, &amp;amp;output_cfg, NULL);
	status = nrfx_gpiote_output_configure(&amp;amp;gpiote_inst, led1_pin, &amp;amp;output_cfg, NULL);

	nrfx_gpiote_trigger_enable(&amp;amp;gpiote_inst, input_trigger_pin_nbr, true);
	nrfx_gpiote_out_task_enable(&amp;amp;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(&amp;amp;timer_inst, NRF_TIMER_CC_CHANNEL0);

	status = nrfx_gppi_conn_alloc(evt_addr_up, task_addr_CC0, &amp;amp;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(&amp;amp;timer_inst, NRF_TIMER_CC_CHANNEL1);

	status = nrfx_gppi_conn_alloc(evt_addr_down, task_addr_CC1, &amp;amp;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(&amp;amp;gpiote_inst, input_trigger_pin_nbr);
	uint32_t task_addr_start = nrfx_timer_task_address_get(&amp;amp;timer_inst, NRF_TIMER_TASK_START);

	status = nrfx_gppi_conn_alloc(evt_addr_start, task_addr_start, &amp;amp;gppi_comp_trigger);
	NRFX_ASSERT(status == NRFX_SUCCESS);
	
	// Enable the connection using the handle
	nrfx_gppi_conn_enable(gppi_comp_trigger);

	LOG_INF(&amp;quot;ddpi_init Done &amp;quot;);
}

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(&amp;amp;timer_inst, &amp;amp;config, NULL);
	if (status != NRFX_SUCCESS) {
		return;
	} else {
		nrfx_timer_clear(&amp;amp;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(&amp;quot;%s is not ready&amp;quot;, comp_dev-&amp;gt;name);
		return 0;
	}
	ret = comparator_set_trigger_callback(comp_dev, lpcomp_callback, NULL);
	if (ret) {
		LOG_ERR(&amp;quot;comparator_set_trigger_callback() failed. (err: %d)&amp;quot;, ret);
		return 0;
	}

	ret = comparator_set_trigger(comp_dev, COMPARATOR_TRIGGER_BOTH_EDGES);
	if (ret) {
		LOG_ERR(&amp;quot;comparator_set_trigger() failed. (err: %d)&amp;quot;, ret);
		return 0;
	}

	LOG_INF(&amp;quot;Starup ok, Entering While loop&amp;quot;);
	while (1) {
		// nrfx_timer_enable(&amp;amp;timer_inst);
		T_rise = 0xFFFFFFFF;
		T_fall = 0xFFFFFFFF;

		LOG_INF(&amp;quot;Triggering SET TASK&amp;quot;);
		nrfx_gpiote_out_task_trigger(&amp;amp;gpiote_inst,comp_trigger_pin_nbr);
		
		LOG_INF(&amp;quot;Triggering TIMER PIN&amp;quot;);
		nrfx_gpiote_out_set(&amp;amp;gpiote_inst,time_trigger_pin_nbr);
		
		LOG_INF(&amp;quot;Toggle LED1&amp;quot;);
		nrfx_gpiote_out_toggle(&amp;amp;gpiote_inst,led1_pin);
		if (ret &amp;lt; 0) {
			return 0;
		}

		if (T_rise != 0xFFFFFFFF &amp;amp;&amp;amp; T_fall != 0xFFFFFFFF) {
			int32_t dt = (int32_t)T_fall - (int32_t)T_rise;
			LOG_INF(&amp;quot;Δt = %d us&amp;quot;, dt);

			/* reset pour nouvelle mesure */
			T_rise = T_fall = 0xFFFFFFFF;
		}

		LOG_INF(&amp;quot;SLEEP\n\n&amp;quot;);
		k_msleep(SLEEP_TIME_MS);
	}
	return 0;
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>