PPI and timers


Hello
I am learning how to connect timers with gpio via PPI, i working on nrf52832dk.

So far I have connected the RTC 0 alarm channel to the LED no.3 (pin no.19) and its state changes every time the timer is called.

I tried to do the same with timer 1 and LED4 (pin no.20) , unfortunately this connection won't work.

I am enclosing the code that theoretically should work, can anyone check this problem?


#include <zephyr.h>
#include <debug/ppi_trace.h>
#include <drivers/counter.h>
#include <hal/nrf_rtc.h>
#include <hal/nrf_clock.h>
#include <hal/nrf_timer.h>
#include <nrfx_timer.h>
#include <device.h>
#include <logging/log.h>

LOG_MODULE_REGISTER(app);

#define ALARM_PERIOD_US 1000 * 1000
#define RTC NRF_RTC2
#define TIMER NRF_TIMER1

#define RTC_LABEL DT_LABEL(DT_NODELABEL(rtc2))
#define TIMER_LABEL DT_LABEL(DT_NODELABEL(timer1))

static void alarm_callback(const struct device *dev, uint8_t chan_id, uint32_t ticks,
						   void *user_data);

static void timer_callback(const struct device *dev, uint8_t chan_id, uint32_t ticks,
						   void *user_data);

static struct counter_alarm_cfg RTC_alarm_cfg = {
	.callback = alarm_callback,
	.flags = COUNTER_ALARM_CFG_ABSOLUTE,
};

static struct counter_alarm_cfg TIM0_alarm_cfg = {
	.callback = timer_callback,
	.flags = 0, //?
};

static void ppi_trace_pin_setup(uint32_t pin, uint32_t evt)
{
	void *handle;

	handle = ppi_trace_config(pin, evt);
	__ASSERT(handle != NULL,
			 "Failed to initialize trace pin, no PPI or GPIOTE resources?");

	ppi_trace_enable(handle);
}


static void ppi_trace_setup(void)
{
	ppi_trace_pin_setup(19,
						nrf_rtc_event_address_get(RTC, NRF_RTC_EVENT_COMPARE_0));
	

	ppi_trace_pin_setup(20, nrf_timer_event_address_get(TIMER, NRF_TIMER_EVENT_COMPARE1));

	LOG_INF("PPI trace setup done.");
}

static void alarm_callback(const struct device *dev, uint8_t chan_id,
						   uint32_t ticks, void *user_data)
{
	int err;
	uint32_t alarm_cnt = (uint32_t)user_data + 1;

	RTC_alarm_cfg.ticks = ticks + counter_us_to_ticks(dev, ALARM_PERIOD_US);
	RTC_alarm_cfg.user_data = (void *)alarm_cnt;
	LOG_INF("alarm_callback");
	err = counter_set_channel_alarm(dev, 0, &RTC_alarm_cfg);
	__ASSERT_NO_MSG(err == 0);
	(void)err;
}

static void timer_callback(const struct device *dev, uint8_t chan_id,
						   uint32_t ticks, void *user_data)
{
	int err;
	uint32_t alarm_cnt = (uint32_t)user_data + 1;

	TIM0_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US/2);
	TIM0_alarm_cfg.user_data = (void *)alarm_cnt;
	LOG_INF("timer_callback %d ",TIM0_alarm_cfg.ticks);
	err = counter_set_channel_alarm(dev, 1, &TIM0_alarm_cfg);
	__ASSERT_NO_MSG(err == 0);
	(void)err;
}

static void counter_setup(void)
{
	{
		int err;
		const struct device *dev = device_get_binding(RTC_LABEL);

		__ASSERT(dev, "Sample cannot run on this board.");

		RTC_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US);
		err = counter_set_channel_alarm(dev, 0, &RTC_alarm_cfg);
		__ASSERT_NO_MSG(err == 0);

		err = counter_start(dev);
		__ASSERT_NO_MSG(err == 0);
	}
	{
		int err;
		const struct device *dev = device_get_binding(TIMER_LABEL);

		__ASSERT(dev, "Sample cannot run on this board.");

		TIM0_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US);

		err = counter_set_channel_alarm(dev, 1, &TIM0_alarm_cfg);
		__ASSERT_NO_MSG(err == 0);

		 err = counter_start(dev);
		__ASSERT_NO_MSG(err == 0);
	}
}

void main(void)
{
	ppi_trace_setup();
	counter_setup();

	while (1)
	{
		k_msleep(1000);
	}
}

Parents
  • I managed to run ppi on a fast timer, it turned out that the "counter_set_channel_alarm" function that was supposed to set an alarm on channel 0 sets it on channel 2.
  • Hi 

    You mean to say you found the problem in your own code, or that there is a bug in the one of the drivers?

    Best regards
    Torbjørn

  • I believe i found problem in driver, but i may be wrong. 

    My code:

    #include <zephyr.h>
    #include <debug/ppi_trace.h>
    #include <drivers/counter.h>
    #include <hal/nrf_rtc.h>
    #include <hal/nrf_clock.h>
    #include <hal/nrf_timer.h>
    #include <nrfx_timer.h>
    #include <device.h>
    #include <logging/log.h>
    
    LOG_MODULE_REGISTER(app);
    #define ALARM_PERIOD_US 1000 * 1000
    #define TIMER NRF_TIMER1
    #define TIMER_LABEL DT_LABEL(DT_NODELABEL(timer1))
    
    static void timer_callback(const struct device *dev, uint8_t chan_id, uint32_t ticks,
    						   void *user_data);
    
    static struct counter_alarm_cfg TIM0_alarm_cfg = {
    	.callback = timer_callback,
    	.flags = 0, //?
    };
    
    static void ppi_trace_pin_setup(uint32_t pin, uint32_t evt)
    {
    	void *handle;
    
    	handle = ppi_trace_config(pin, evt);
    	__ASSERT(handle != NULL,
    			 "Failed to initialize trace pin, no PPI or GPIOTE resources?");
    
    	ppi_trace_enable(handle);
    }
    
    static void ppi_trace_setup(void)
    {
    	ppi_trace_pin_setup(19, nrf_timer_event_address_get(TIMER, NRF_TIMER_EVENT_COMPARE0));
    
    	ppi_trace_pin_setup(20, nrf_timer_event_address_get(TIMER, NRF_TIMER_EVENT_COMPARE2));
    
    	LOG_INF("PPI trace setup done.");
    }
    
    static void timer_callback(const struct device *dev, uint8_t chan_id,
    						   uint32_t ticks, void *user_data)
    {
    	int err;
    	uint32_t alarm_cnt = (uint32_t)user_data + 1;
    
    	TIM0_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US );
    	TIM0_alarm_cfg.user_data = (void *)alarm_cnt;
    	LOG_INF("timer_callback %d ", TIM0_alarm_cfg.ticks);
    	err = counter_set_channel_alarm(dev, 0, &TIM0_alarm_cfg);
    	__ASSERT_NO_MSG(err == 0);
    	(void)err;
    }
    
    static void counter_setup(void)
    {
    	int err;
    	const struct device *dev = device_get_binding(TIMER_LABEL);
    
    	__ASSERT(dev, "Sample cannot run on this board.");
    
    	TIM0_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US);
    
    	err = counter_set_channel_alarm(dev, 0, &TIM0_alarm_cfg);
    	__ASSERT_NO_MSG(err == 0);
    
    	err = counter_start(dev);
    	__ASSERT_NO_MSG(err == 0);
    }
    
    void main(void)
    {
    	ppi_trace_setup();
    	counter_setup();
    
    	while (1)
    	{
    		k_msleep(1000);
    	}
    }
    

    Description: 

    I working on nrf52832 dk.

    The problem is with the wrong selection of the timer alarm channel. I call function which should use channel 0 timer 1

    counter_set_channel_alarm(dev_tim, NRF_TIMER_CC_CHANNEL0, &TIM0_alarm_cfg);

    But the driver has assigned an alarm interrupt on channel 2, you can see it in the CPU registers. ( active interrupt 2 not 0)

Reply
  • I believe i found problem in driver, but i may be wrong. 

    My code:

    #include <zephyr.h>
    #include <debug/ppi_trace.h>
    #include <drivers/counter.h>
    #include <hal/nrf_rtc.h>
    #include <hal/nrf_clock.h>
    #include <hal/nrf_timer.h>
    #include <nrfx_timer.h>
    #include <device.h>
    #include <logging/log.h>
    
    LOG_MODULE_REGISTER(app);
    #define ALARM_PERIOD_US 1000 * 1000
    #define TIMER NRF_TIMER1
    #define TIMER_LABEL DT_LABEL(DT_NODELABEL(timer1))
    
    static void timer_callback(const struct device *dev, uint8_t chan_id, uint32_t ticks,
    						   void *user_data);
    
    static struct counter_alarm_cfg TIM0_alarm_cfg = {
    	.callback = timer_callback,
    	.flags = 0, //?
    };
    
    static void ppi_trace_pin_setup(uint32_t pin, uint32_t evt)
    {
    	void *handle;
    
    	handle = ppi_trace_config(pin, evt);
    	__ASSERT(handle != NULL,
    			 "Failed to initialize trace pin, no PPI or GPIOTE resources?");
    
    	ppi_trace_enable(handle);
    }
    
    static void ppi_trace_setup(void)
    {
    	ppi_trace_pin_setup(19, nrf_timer_event_address_get(TIMER, NRF_TIMER_EVENT_COMPARE0));
    
    	ppi_trace_pin_setup(20, nrf_timer_event_address_get(TIMER, NRF_TIMER_EVENT_COMPARE2));
    
    	LOG_INF("PPI trace setup done.");
    }
    
    static void timer_callback(const struct device *dev, uint8_t chan_id,
    						   uint32_t ticks, void *user_data)
    {
    	int err;
    	uint32_t alarm_cnt = (uint32_t)user_data + 1;
    
    	TIM0_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US );
    	TIM0_alarm_cfg.user_data = (void *)alarm_cnt;
    	LOG_INF("timer_callback %d ", TIM0_alarm_cfg.ticks);
    	err = counter_set_channel_alarm(dev, 0, &TIM0_alarm_cfg);
    	__ASSERT_NO_MSG(err == 0);
    	(void)err;
    }
    
    static void counter_setup(void)
    {
    	int err;
    	const struct device *dev = device_get_binding(TIMER_LABEL);
    
    	__ASSERT(dev, "Sample cannot run on this board.");
    
    	TIM0_alarm_cfg.ticks = counter_us_to_ticks(dev, ALARM_PERIOD_US);
    
    	err = counter_set_channel_alarm(dev, 0, &TIM0_alarm_cfg);
    	__ASSERT_NO_MSG(err == 0);
    
    	err = counter_start(dev);
    	__ASSERT_NO_MSG(err == 0);
    }
    
    void main(void)
    {
    	ppi_trace_setup();
    	counter_setup();
    
    	while (1)
    	{
    		k_msleep(1000);
    	}
    }
    

    Description: 

    I working on nrf52832 dk.

    The problem is with the wrong selection of the timer alarm channel. I call function which should use channel 0 timer 1

    counter_set_channel_alarm(dev_tim, NRF_TIMER_CC_CHANNEL0, &TIM0_alarm_cfg);

    But the driver has assigned an alarm interrupt on channel 2, you can see it in the CPU registers. ( active interrupt 2 not 0)

Children
Related