1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <cmsis_os.h>
9 #include <string.h>
10 
11 #define ACTIVE 1
12 #define NOT_ACTIVE 0
13 
14 static void zephyr_timer_wrapper(struct k_timer *timer);
15 
16 struct timer_obj {
17 	struct k_timer ztimer;
18 	os_timer_type type;
19 	uint32_t status;
20 	void (*callback_function)(void const *argument);
21 	void *arg;
22 };
23 
24 K_MEM_SLAB_DEFINE(cmsis_timer_slab, sizeof(struct timer_obj),
25 		  CONFIG_CMSIS_TIMER_MAX_COUNT, __alignof__(struct timer_obj));
26 
zephyr_timer_wrapper(struct k_timer * timer)27 static void zephyr_timer_wrapper(struct k_timer *timer)
28 {
29 	struct timer_obj *cm_timer;
30 
31 	cm_timer = CONTAINER_OF(timer, struct timer_obj, ztimer);
32 	(cm_timer->callback_function)(cm_timer->arg);
33 }
34 
35 /**
36  * @brief Create a Timer
37  */
osTimerCreate(const osTimerDef_t * timer_def,os_timer_type type,void * argument)38 osTimerId osTimerCreate(const osTimerDef_t *timer_def, os_timer_type type,
39 			void *argument)
40 {
41 	struct timer_obj *timer;
42 
43 	if (timer_def == NULL) {
44 		return NULL;
45 	}
46 
47 	if (type != osTimerOnce && type != osTimerPeriodic) {
48 		return NULL;
49 	}
50 
51 	if (k_mem_slab_alloc(&cmsis_timer_slab, (void **)&timer, K_MSEC(100)) == 0) {
52 		(void)memset(timer, 0, sizeof(struct timer_obj));
53 	} else {
54 		return NULL;
55 	}
56 
57 	timer->callback_function = timer_def->ptimer;
58 	timer->arg = argument;
59 	timer->type = type;
60 	timer->status = NOT_ACTIVE;
61 
62 	k_timer_init(&timer->ztimer, zephyr_timer_wrapper, NULL);
63 
64 	return (osTimerId)timer;
65 }
66 
67 /**
68  * @brief Start or restart a Timer
69  */
osTimerStart(osTimerId timer_id,uint32_t millisec)70 osStatus osTimerStart(osTimerId timer_id, uint32_t millisec)
71 {
72 	struct timer_obj *timer = (struct timer_obj *) timer_id;
73 
74 	if (timer == NULL) {
75 		return osErrorParameter;
76 	}
77 
78 	if (k_is_in_isr()) {
79 		return osErrorISR;
80 	}
81 
82 	if (timer->type == osTimerOnce) {
83 		k_timer_start(&timer->ztimer, K_MSEC(millisec), K_NO_WAIT);
84 	} else if (timer->type == osTimerPeriodic) {
85 		k_timer_start(&timer->ztimer, K_MSEC(millisec),
86 			      K_MSEC(millisec));
87 	}
88 
89 	timer->status = ACTIVE;
90 	return osOK;
91 }
92 
93 /**
94  * @brief Stop the Timer
95  */
osTimerStop(osTimerId timer_id)96 osStatus osTimerStop(osTimerId timer_id)
97 {
98 	struct timer_obj *timer = (struct timer_obj *) timer_id;
99 
100 	if (timer == NULL) {
101 		return osErrorParameter;
102 	}
103 
104 	if (k_is_in_isr()) {
105 		return osErrorISR;
106 	}
107 
108 	if (timer->status == NOT_ACTIVE) {
109 		return osErrorResource;
110 	}
111 
112 	k_timer_stop(&timer->ztimer);
113 	timer->status = NOT_ACTIVE;
114 	return osOK;
115 }
116 
117 /**
118  * @brief Delete the timer that was created by osTimerCreate
119  */
osTimerDelete(osTimerId timer_id)120 osStatus osTimerDelete(osTimerId timer_id)
121 {
122 	struct timer_obj *timer = (struct timer_obj *) timer_id;
123 
124 	if (timer == NULL) {
125 		return osErrorParameter;
126 	}
127 
128 	if (k_is_in_isr()) {
129 		return osErrorISR;
130 	}
131 
132 	if (timer->status == ACTIVE) {
133 		k_timer_stop(&timer->ztimer);
134 		timer->status = NOT_ACTIVE;
135 	}
136 
137 	k_mem_slab_free(&cmsis_timer_slab, (void *)timer);
138 	return osOK;
139 }
140