1 /*
2  * Copyright (c) 2019 Linaro Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/counter.h>
11 #include <zephyr/sys/printk.h>
12 
13 #define DELAY 2000000
14 #define ALARM_CHANNEL_ID 0
15 
16 struct counter_alarm_cfg alarm_cfg;
17 
18 #if defined(CONFIG_BOARD_SAMD20_XPRO)
19 #define TIMER DT_NODELABEL(tc4)
20 #elif defined(CONFIG_SOC_FAMILY_ATMEL_SAM)
21 #define TIMER DT_NODELABEL(tc0)
22 #elif defined(CONFIG_COUNTER_MICROCHIP_MCP7940N)
23 #define TIMER DT_NODELABEL(extrtc0)
24 #elif defined(CONFIG_COUNTER_NRF_RTC)
25 #define TIMER DT_NODELABEL(rtc0)
26 #elif defined(CONFIG_COUNTER_NRF_TIMER)
27 #define TIMER DT_CHOSEN(counter)
28 #elif defined(CONFIG_COUNTER_TIMER_STM32)
29 #define TIMER DT_INST(0, st_stm32_counter)
30 #elif defined(CONFIG_COUNTER_RTC_STM32)
31 #define TIMER DT_INST(0, st_stm32_rtc)
32 #elif defined(CONFIG_COUNTER_SMARTBOND_TIMER)
33 #define TIMER DT_NODELABEL(timer3)
34 #elif defined(CONFIG_COUNTER_NATIVE_POSIX)
35 #define TIMER DT_NODELABEL(counter0)
36 #elif defined(CONFIG_COUNTER_XLNX_AXI_TIMER)
37 #define TIMER DT_INST(0, xlnx_xps_timer_1_00_a)
38 #elif defined(CONFIG_COUNTER_TMR_ESP32)
39 #define TIMER DT_NODELABEL(timer0)
40 #elif defined(CONFIG_COUNTER_MCUX_CTIMER)
41 #define TIMER DT_NODELABEL(ctimer0)
42 #elif defined(CONFIG_COUNTER_NXP_S32_SYS_TIMER)
43 #define TIMER DT_NODELABEL(stm0)
44 #elif defined(CONFIG_COUNTER_TIMER_GD32)
45 #define TIMER DT_NODELABEL(timer0)
46 #elif defined(CONFIG_COUNTER_GECKO_RTCC)
47 #define TIMER DT_NODELABEL(rtcc0)
48 #elif defined(CONFIG_COUNTER_GECKO_STIMER)
49 #define TIMER DT_NODELABEL(stimer0)
50 #elif defined(CONFIG_COUNTER_INFINEON_CAT1)
51 #define TIMER DT_NODELABEL(counter0_0)
52 #elif defined(CONFIG_COUNTER_AMBIQ)
53 #define TIMER DT_NODELABEL(counter0)
54 #elif defined(CONFIG_COUNTER_SNPS_DW)
55 #define TIMER DT_NODELABEL(timer0)
56 #elif defined(CONFIG_COUNTER_TIMER_RPI_PICO)
57 #define TIMER DT_NODELABEL(timer)
58 #elif defined(CONFIG_COUNTER_TIMER_MAX32)
59 #define TIMER DT_NODELABEL(counter0)
60 #elif defined(CONFIG_COUNTER_RA_AGT)
61 #define TIMER DT_NODELABEL(counter0)
62 #else
63 #error Unable to find a counter device node in devicetree
64 #endif
65 
test_counter_interrupt_fn(const struct device * counter_dev,uint8_t chan_id,uint32_t ticks,void * user_data)66 static void test_counter_interrupt_fn(const struct device *counter_dev,
67 				      uint8_t chan_id, uint32_t ticks,
68 				      void *user_data)
69 {
70 	struct counter_alarm_cfg *config = user_data;
71 	uint32_t now_ticks;
72 	uint64_t now_usec;
73 	int now_sec;
74 	int err;
75 
76 	err = counter_get_value(counter_dev, &now_ticks);
77 	if (!counter_is_counting_up(counter_dev)) {
78 		now_ticks = counter_get_top_value(counter_dev) - now_ticks;
79 	}
80 
81 	if (err) {
82 		printk("Failed to read counter value (err %d)", err);
83 		return;
84 	}
85 
86 	now_usec = counter_ticks_to_us(counter_dev, now_ticks);
87 	now_sec = (int)(now_usec / USEC_PER_SEC);
88 
89 	printk("!!! Alarm !!!\n");
90 	printk("Now: %u\n", now_sec);
91 
92 	/* Set a new alarm with a double length duration */
93 	config->ticks = config->ticks * 2U;
94 
95 	printk("Set alarm in %u sec (%u ticks)\n",
96 	       (uint32_t)(counter_ticks_to_us(counter_dev,
97 					   config->ticks) / USEC_PER_SEC),
98 	       config->ticks);
99 
100 	err = counter_set_channel_alarm(counter_dev, ALARM_CHANNEL_ID,
101 					user_data);
102 	if (err != 0) {
103 		printk("Alarm could not be set\n");
104 	}
105 }
106 
main(void)107 int main(void)
108 {
109 	const struct device *const counter_dev = DEVICE_DT_GET(TIMER);
110 	int err;
111 
112 	printk("Counter alarm sample\n\n");
113 
114 	if (!device_is_ready(counter_dev)) {
115 		printk("device not ready.\n");
116 		return 0;
117 	}
118 
119 	counter_start(counter_dev);
120 
121 	alarm_cfg.flags = 0;
122 	alarm_cfg.ticks = counter_us_to_ticks(counter_dev, DELAY);
123 	alarm_cfg.callback = test_counter_interrupt_fn;
124 	alarm_cfg.user_data = &alarm_cfg;
125 
126 	err = counter_set_channel_alarm(counter_dev, ALARM_CHANNEL_ID,
127 					&alarm_cfg);
128 	printk("Set alarm in %u sec (%u ticks)\n",
129 	       (uint32_t)(counter_ticks_to_us(counter_dev,
130 					   alarm_cfg.ticks) / USEC_PER_SEC),
131 	       alarm_cfg.ticks);
132 
133 	if (-EINVAL == err) {
134 		printk("Alarm settings invalid\n");
135 	} else if (-ENOTSUP == err) {
136 		printk("Alarm setting request not supported\n");
137 	} else if (err != 0) {
138 		printk("Error\n");
139 	}
140 
141 	while (1) {
142 		k_sleep(K_FOREVER);
143 	}
144 	return 0;
145 }
146