1 /*
2 * Copyright (c) 2017, Texas Instruments Incorporated
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr.h>
8 #include <sys/__assert.h>
9 #include <kernel/zephyr/dpl/dpl.h>
10 #include <ti/drivers/dpl/ClockP.h>
11
12 #include "stubs.h"
13
14 /*
15 * ClockP_STRUCT_SIZE in ClockP.h must be updated to match the size of this
16 * struct
17 */
18 typedef struct _ClockP_Obj {
19 struct k_timer timer;
20 ClockP_Fxn clock_fxn;
21 uintptr_t arg;
22 uint32_t timeout;
23 uint32_t period;
24 bool active;
25 } ClockP_Obj;
26
27 static ClockP_Params ClockP_defaultParams = {
28 .startFlag = false,
29 .period = 0,
30 .arg = 0,
31 };
32
expiry_fxn(struct k_timer * timer_id)33 static void expiry_fxn(struct k_timer *timer_id)
34 {
35 ClockP_Obj *obj = (ClockP_Obj *)k_timer_user_data_get(timer_id);
36
37 obj->clock_fxn(obj->arg);
38 }
39
40 /*
41 * ======== ClockP_construct ========
42 */
ClockP_construct(ClockP_Struct * handle,ClockP_Fxn clockFxn,uint32_t timeout,ClockP_Params * params)43 ClockP_Handle ClockP_construct(ClockP_Struct *handle, ClockP_Fxn clockFxn,
44 uint32_t timeout, ClockP_Params *params)
45 {
46 ClockP_Obj *obj = (ClockP_Obj *)handle;
47
48 if (handle == NULL) {
49 return NULL;
50 }
51
52 if (params == NULL) {
53 params = &ClockP_defaultParams;
54 }
55
56 obj->clock_fxn = clockFxn;
57 obj->arg = params->arg;
58 obj->period = params->period * ClockP_getSystemTickPeriod() / 1000;
59 obj->timeout = timeout;
60 obj->active = false;
61
62 k_timer_init(&obj->timer, expiry_fxn, NULL);
63 k_timer_user_data_set(&obj->timer, obj);
64
65 if (params->startFlag) {
66 ClockP_start(obj);
67 }
68
69 return ((ClockP_Handle)handle);
70 }
71
72 /*
73 * ======== ClockP_getSystemTickPeriod ========
74 */
75 uint32_t ClockP_tickPeriod = (1000000 / CONFIG_SYS_CLOCK_TICKS_PER_SEC);
ClockP_getSystemTickPeriod()76 uint32_t ClockP_getSystemTickPeriod()
77 {
78 return ClockP_tickPeriod;
79 }
80
ClockP_getSystemTicks()81 uint32_t ClockP_getSystemTicks()
82 {
83 return (uint32_t)k_ms_to_ticks_ceil32(k_uptime_get_32());
84 }
85
86 /*
87 * ======== ClockP_Params_init ========
88 */
ClockP_Params_init(ClockP_Params * params)89 void ClockP_Params_init(ClockP_Params *params)
90 {
91 params->arg = 0;
92 params->startFlag = false;
93 params->period = 0;
94 }
95
96 /*
97 * ======== ClockP_setTimeout ========
98 */
ClockP_setTimeout(ClockP_Handle handle,uint32_t timeout)99 void ClockP_setTimeout(ClockP_Handle handle, uint32_t timeout)
100 {
101 ClockP_Obj *obj = (ClockP_Obj *)handle;
102
103 obj->timeout = timeout;
104 }
105
106 /*
107 * ======== ClockP_start ========
108 */
ClockP_start(ClockP_Handle handle)109 void ClockP_start(ClockP_Handle handle)
110 {
111 ClockP_Obj *obj = (ClockP_Obj *)handle;
112 int32_t timeout;
113 int32_t period;
114
115 __ASSERT_NO_MSG(obj->timeout /
116 CONFIG_SYS_CLOCK_TICKS_PER_SEC <= UINT32_MAX / 1000);
117 __ASSERT_NO_MSG(obj->period /
118 CONFIG_SYS_CLOCK_TICKS_PER_SEC <= UINT32_MAX / 1000);
119
120 /* Avoid overflow */
121 if (obj->timeout > UINT32_MAX / 1000) {
122 timeout = obj->timeout / CONFIG_SYS_CLOCK_TICKS_PER_SEC * 1000;
123 } else if ((obj->timeout != 0) &&
124 (obj->timeout < CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000)) {
125 /* For small timeouts we use 1 msec */
126 timeout = 1;
127 } else {
128 timeout = obj->timeout * 1000 / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
129 }
130
131 if (obj->period > UINT32_MAX / 1000) {
132 period = obj->period / CONFIG_SYS_CLOCK_TICKS_PER_SEC * 1000;
133 } else if ((obj->period != 0) &&
134 (obj->period < CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000)) {
135 period = 1;
136 } else {
137 period = obj->period * 1000 / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
138 }
139
140 k_timer_start(&obj->timer, K_MSEC(timeout), K_MSEC(period));
141
142 obj->active = true;
143 }
144
145 /*
146 * ======== ClockP_stop ========
147 */
ClockP_stop(ClockP_Handle handle)148 void ClockP_stop(ClockP_Handle handle)
149 {
150 ClockP_Obj *obj = (ClockP_Obj *)handle;
151
152 k_timer_stop(&obj->timer);
153 obj->active = false;
154 }
155
156 /*
157 * ======== ClockP_usleep ========
158 */
ClockP_usleep(uint32_t usec)159 void ClockP_usleep(uint32_t usec)
160 {
161 k_sleep(K_USEC(usec));
162 }
163
164 /*
165 * ======== ClockP_getTimeout ========
166 */
ClockP_getTimeout(ClockP_Handle handle)167 uint32_t ClockP_getTimeout(ClockP_Handle handle) {
168 ClockP_Obj *obj = (ClockP_Obj *)handle;
169 return k_timer_remaining_get(&obj->timer) * CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000;
170 }
171
172 /*
173 * ======== ClockP_isActive ========
174 */
ClockP_isActive(ClockP_Handle handle)175 bool ClockP_isActive(ClockP_Handle handle) {
176 ClockP_Obj *obj = (ClockP_Obj *)handle;
177 return obj->active;
178 }
179
ClockP_destruct(ClockP_Struct * clockP)180 void ClockP_destruct(ClockP_Struct *clockP)
181 {
182 ClockP_Obj *obj = (ClockP_Obj *)clockP->data;
183
184 obj->clock_fxn = NULL;
185 obj->arg = 0;
186 obj->period = 0;
187 obj->timeout = 0;
188 obj->active = false;
189
190 k_timer_stop(&obj->timer);
191 }
192