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 K_MEM_SLAB_DEFINE(cv2_semaphore_slab, sizeof(struct cv2_sem),
12 CONFIG_CMSIS_V2_SEMAPHORE_MAX_COUNT, 4);
13
14 static const osSemaphoreAttr_t init_sema_attrs = {
15 .name = "ZephyrSem",
16 .attr_bits = 0,
17 .cb_mem = NULL,
18 .cb_size = 0,
19 };
20
21 /**
22 * @brief Create and Initialize a semaphore object.
23 */
osSemaphoreNew(uint32_t max_count,uint32_t initial_count,const osSemaphoreAttr_t * attr)24 osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count,
25 const osSemaphoreAttr_t *attr)
26 {
27 struct cv2_sem *semaphore;
28
29 if (k_is_in_isr()) {
30 return NULL;
31 }
32
33 if (attr == NULL) {
34 attr = &init_sema_attrs;
35 }
36
37 if (k_mem_slab_alloc(&cv2_semaphore_slab,
38 (void **)&semaphore, K_MSEC(100)) == 0) {
39 (void)memset(semaphore, 0, sizeof(struct cv2_sem));
40 } else {
41 return NULL;
42 }
43
44 k_sem_init(&semaphore->z_semaphore, initial_count, max_count);
45
46 if (attr->name == NULL) {
47 strncpy(semaphore->name, init_sema_attrs.name,
48 sizeof(semaphore->name) - 1);
49 } else {
50 strncpy(semaphore->name, attr->name,
51 sizeof(semaphore->name) - 1);
52 }
53
54 return (osSemaphoreId_t)semaphore;
55 }
56
57 /**
58 * @brief Wait until a semaphore becomes available.
59 */
osSemaphoreAcquire(osSemaphoreId_t semaphore_id,uint32_t timeout)60 osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
61 {
62 struct cv2_sem *semaphore = (struct cv2_sem *) semaphore_id;
63 int status;
64
65 if (semaphore_id == NULL) {
66 return osErrorParameter;
67 }
68
69 /* Can be called from ISRs only if timeout is set to 0 */
70 if (timeout > 0 && k_is_in_isr()) {
71 return osErrorParameter;
72 }
73
74 if (timeout == osWaitForever) {
75 status = k_sem_take(&semaphore->z_semaphore, K_FOREVER);
76 } else if (timeout == 0U) {
77 status = k_sem_take(&semaphore->z_semaphore, K_NO_WAIT);
78 } else {
79 status = k_sem_take(&semaphore->z_semaphore,
80 K_TICKS(timeout));
81 }
82
83 if (status == -EBUSY) {
84 return osErrorResource;
85 } else if (status == -EAGAIN) {
86 return osErrorTimeout;
87 } else {
88 return osOK;
89 }
90 }
91
osSemaphoreGetCount(osSemaphoreId_t semaphore_id)92 uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
93 {
94 struct cv2_sem *semaphore = (struct cv2_sem *)semaphore_id;
95
96 if (semaphore_id == NULL) {
97 return 0;
98 }
99
100 return k_sem_count_get(&semaphore->z_semaphore);
101 }
102
103 /**
104 * @brief Release a semaphore that was obtained by osSemaphoreWait.
105 */
osSemaphoreRelease(osSemaphoreId_t semaphore_id)106 osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
107 {
108 struct cv2_sem *semaphore = (struct cv2_sem *) semaphore_id;
109
110 if (semaphore_id == NULL) {
111 return osErrorParameter;
112 }
113
114 /* All tokens have already been released */
115 if (k_sem_count_get(&semaphore->z_semaphore) ==
116 semaphore->z_semaphore.limit) {
117 return osErrorResource;
118 }
119
120 k_sem_give(&semaphore->z_semaphore);
121
122 return osOK;
123 }
124
125 /**
126 * @brief Delete a semaphore that was created by osSemaphoreCreate.
127 */
osSemaphoreDelete(osSemaphoreId_t semaphore_id)128 osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id)
129 {
130 struct cv2_sem *semaphore = (struct cv2_sem *)semaphore_id;
131
132 if (semaphore_id == NULL) {
133 return osErrorParameter;
134 }
135
136 if (k_is_in_isr()) {
137 return osErrorISR;
138 }
139
140 /* The status code "osErrorResource" (the semaphore specified by
141 * parameter semaphore_id is in an invalid semaphore state) is not
142 * supported in Zephyr.
143 */
144
145 k_mem_slab_free(&cv2_semaphore_slab, (void *) &semaphore);
146
147 return osOK;
148 }
149
osSemaphoreGetName(osSemaphoreId_t semaphore_id)150 const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
151 {
152 struct cv2_sem *semaphore = (struct cv2_sem *)semaphore_id;
153
154 if (!k_is_in_isr() && (semaphore_id != NULL)) {
155 return semaphore->name;
156 } else {
157 return NULL;
158 }
159 }
160