1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  * Copyright (c) 2024 NXP.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define LOG_MODULE_NAME net_openthread_alarm
9 #define LOG_LEVEL CONFIG_OPENTHREAD_LOG_LEVEL
10 
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
13 
14 #include <zephyr/kernel.h>
15 #include <string.h>
16 #include <inttypes.h>
17 
18 #include <openthread/platform/alarm-milli.h>
19 #include <openthread/platform/alarm-micro.h>
20 #include <openthread/platform/diag.h>
21 #include <openthread-system.h>
22 
23 #include <stdio.h>
24 
25 #include "platform-zephyr.h"
26 #include "openthread-core-zephyr-config.h"
27 
28 static bool timer_ms_fired, timer_us_fired;
29 static int32_t time_offset_us;
30 static int32_t time_offset_ms;
31 
ot_timer_ms_fired(struct k_timer * timer)32 static void ot_timer_ms_fired(struct k_timer *timer)
33 {
34 	ARG_UNUSED(timer);
35 
36 	timer_ms_fired = true;
37 	otSysEventSignalPending();
38 }
39 
ot_timer_us_fired(struct k_timer * timer)40 static void ot_timer_us_fired(struct k_timer *timer)
41 {
42 	ARG_UNUSED(timer);
43 
44 	timer_us_fired = true;
45 	otSysEventSignalPending();
46 }
47 
48 K_TIMER_DEFINE(ot_ms_timer, ot_timer_ms_fired, NULL);
49 K_TIMER_DEFINE(ot_us_timer, ot_timer_us_fired, NULL);
50 
platformAlarmInit(void)51 void platformAlarmInit(void)
52 {
53 #if defined(CONFIG_NET_PKT_TXTIME)
54 	time_offset_us =
55 		(int32_t)((int64_t)otPlatAlarmMicroGetNow() - (uint32_t)otPlatRadioGetNow(NULL));
56 	time_offset_ms = time_offset_us / 1000;
57 #endif
58 }
59 
platformAlarmProcess(otInstance * aInstance)60 void platformAlarmProcess(otInstance *aInstance)
61 {
62 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
63 	if (timer_us_fired) {
64 		timer_us_fired = false;
65 		otPlatAlarmMicroFired(aInstance);
66 	}
67 #endif
68 	if (timer_ms_fired) {
69 		timer_ms_fired = false;
70 #if defined(CONFIG_OPENTHREAD_DIAG)
71 		if (otPlatDiagModeGet()) {
72 			otPlatDiagAlarmFired(aInstance);
73 		} else
74 #endif
75 		{
76 			otPlatAlarmMilliFired(aInstance);
77 		}
78 	}
79 }
80 
otPlatAlarmMilliGetNow(void)81 uint32_t otPlatAlarmMilliGetNow(void)
82 {
83 	return k_uptime_get_32() - time_offset_ms;
84 }
85 
otPlatAlarmMilliStartAt(otInstance * aInstance,uint32_t aT0,uint32_t aDt)86 void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
87 {
88 	ARG_UNUSED(aInstance);
89 
90 	int32_t delta = (int32_t)(aT0 + aDt - otPlatAlarmMilliGetNow());
91 
92 	if (delta > 0) {
93 		k_timer_start(&ot_ms_timer, K_MSEC(delta), K_NO_WAIT);
94 	} else {
95 		ot_timer_ms_fired(NULL);
96 	}
97 }
98 
otPlatAlarmMilliStop(otInstance * aInstance)99 void otPlatAlarmMilliStop(otInstance *aInstance)
100 {
101 	ARG_UNUSED(aInstance);
102 
103 	k_timer_stop(&ot_ms_timer);
104 }
105 
otPlatAlarmMicroStartAt(otInstance * aInstance,uint32_t aT0,uint32_t aDt)106 void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
107 {
108 	ARG_UNUSED(aInstance);
109 
110 	int32_t delta = (int32_t)(aT0 + aDt - otPlatAlarmMicroGetNow());
111 
112 	if (delta > 0) {
113 		k_timer_start(&ot_us_timer, K_USEC(delta), K_NO_WAIT);
114 	} else {
115 		ot_timer_us_fired(NULL);
116 	}
117 }
118 
otPlatAlarmMicroStop(otInstance * aInstance)119 void otPlatAlarmMicroStop(otInstance *aInstance)
120 {
121 	ARG_UNUSED(aInstance);
122 
123 	k_timer_stop(&ot_us_timer);
124 }
125 
otPlatAlarmMicroGetNow(void)126 uint32_t otPlatAlarmMicroGetNow(void)
127 {
128 	return (uint32_t)(k_ticks_to_us_floor64(k_uptime_ticks()) - time_offset_us);
129 }
130 
otPlatTimeGetXtalAccuracy(void)131 uint16_t otPlatTimeGetXtalAccuracy(void)
132 {
133 	return otPlatRadioGetCslAccuracy(NULL);
134 }
135 
136 #ifdef CONFIG_HDLC_RCP_IF
otPlatTimeGet(void)137 uint64_t otPlatTimeGet(void)
138 {
139 	return k_ticks_to_us_floor64(k_uptime_ticks());
140 }
141 #endif
142