1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <string.h>
9 #include "wrapper.h"
10 
11 #define ACTIVE 1
12 #define NOT_ACTIVE 0
13 
14 static void zephyr_timer_wrapper(struct k_timer *timer);
15 
16 K_MEM_SLAB_DEFINE(cv2_timer_slab, sizeof(struct cv2_timer),
17 		  CONFIG_CMSIS_V2_TIMER_MAX_COUNT, 4);
18 
19 static const osTimerAttr_t init_timer_attrs = {
20 	.name = "ZephyrTimer",
21 	.attr_bits = 0,
22 	.cb_mem = NULL,
23 	.cb_size = 0,
24 };
25 
zephyr_timer_wrapper(struct k_timer * timer)26 static void zephyr_timer_wrapper(struct k_timer *timer)
27 {
28 	struct cv2_timer *cm_timer;
29 
30 	cm_timer = CONTAINER_OF(timer, struct cv2_timer, z_timer);
31 	(cm_timer->callback_function)(cm_timer->arg);
32 }
33 
34 /**
35  * @brief Create a Timer
36  */
osTimerNew(osTimerFunc_t func,osTimerType_t type,void * argument,const osTimerAttr_t * attr)37 osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type,
38 		       void *argument, const osTimerAttr_t *attr)
39 {
40 	struct cv2_timer *timer;
41 
42 	if (type != osTimerOnce && type != osTimerPeriodic) {
43 		return NULL;
44 	}
45 
46 	if (k_is_in_isr()) {
47 		return NULL;
48 	}
49 
50 	if (attr == NULL) {
51 		attr = &init_timer_attrs;
52 	}
53 
54 	if (k_mem_slab_alloc(&cv2_timer_slab, (void **)&timer, K_MSEC(100)) == 0) {
55 		(void)memset(timer, 0, sizeof(struct cv2_timer));
56 	} else {
57 		return NULL;
58 	}
59 
60 	timer->callback_function = func;
61 	timer->arg = argument;
62 	timer->type = type;
63 	timer->status = NOT_ACTIVE;
64 
65 	k_timer_init(&timer->z_timer, zephyr_timer_wrapper, NULL);
66 
67 	if (attr->name == NULL) {
68 		strncpy(timer->name, init_timer_attrs.name,
69 			sizeof(timer->name) - 1);
70 	} else {
71 		strncpy(timer->name, attr->name, sizeof(timer->name) - 1);
72 	}
73 
74 	return (osTimerId_t)timer;
75 }
76 
77 /**
78  * @brief Start or restart a Timer
79  */
osTimerStart(osTimerId_t timer_id,uint32_t ticks)80 osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks)
81 {
82 	struct cv2_timer *timer = (struct cv2_timer *)timer_id;
83 
84 	if (timer == NULL) {
85 		return osErrorParameter;
86 	}
87 
88 	if (k_is_in_isr()) {
89 		return osErrorISR;
90 	}
91 
92 	if (timer->type == osTimerOnce) {
93 		k_timer_start(&timer->z_timer, K_TICKS(ticks), K_NO_WAIT);
94 	} else if (timer->type == osTimerPeriodic) {
95 		k_timer_start(&timer->z_timer,
96 			      K_TICKS(ticks), K_TICKS(ticks));
97 	}
98 
99 	timer->status = ACTIVE;
100 	return osOK;
101 }
102 
103 /**
104  * @brief Stop the Timer
105  */
osTimerStop(osTimerId_t timer_id)106 osStatus_t osTimerStop(osTimerId_t timer_id)
107 {
108 	struct cv2_timer *timer = (struct cv2_timer *)timer_id;
109 
110 	if (timer == NULL) {
111 		return osErrorParameter;
112 	}
113 
114 	if (k_is_in_isr()) {
115 		return osErrorISR;
116 	}
117 
118 	if (timer->status == NOT_ACTIVE) {
119 		return osErrorResource;
120 	}
121 
122 	k_timer_stop(&timer->z_timer);
123 	timer->status = NOT_ACTIVE;
124 	return osOK;
125 }
126 
127 /**
128  * @brief Delete the timer that was created by osTimerCreate
129  */
osTimerDelete(osTimerId_t timer_id)130 osStatus_t osTimerDelete(osTimerId_t timer_id)
131 {
132 	struct cv2_timer *timer = (struct cv2_timer *) timer_id;
133 
134 	if (timer == NULL) {
135 		return osErrorParameter;
136 	}
137 
138 	if (k_is_in_isr()) {
139 		return osErrorISR;
140 	}
141 
142 	if (timer->status == ACTIVE) {
143 		k_timer_stop(&timer->z_timer);
144 		timer->status = NOT_ACTIVE;
145 	}
146 
147 	k_mem_slab_free(&cv2_timer_slab, (void *)timer);
148 	return osOK;
149 }
150 
151 /**
152  * @brief Get name of a timer.
153  */
osTimerGetName(osTimerId_t timer_id)154 const char *osTimerGetName(osTimerId_t timer_id)
155 {
156 	struct cv2_timer *timer = (struct cv2_timer *)timer_id;
157 
158 	if (k_is_in_isr() || (timer == NULL)) {
159 		return NULL;
160 	}
161 
162 	return timer->name;
163 }
164 
165 /**
166  * @brief Check if a timer is running.
167  */
osTimerIsRunning(osTimerId_t timer_id)168 uint32_t osTimerIsRunning(osTimerId_t timer_id)
169 {
170 	struct cv2_timer *timer = (struct cv2_timer *)timer_id;
171 
172 	if (k_is_in_isr() || (timer == NULL)) {
173 		return 0;
174 	}
175 
176 	return !(!(k_timer_remaining_get(&timer->z_timer)));
177 }
178