1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/portability/cmsis_types.h>
9 #include <string.h>
10
11 K_MEM_SLAB_DEFINE(cmsis_rtos_semaphore_cb_slab, sizeof(struct cmsis_rtos_semaphore_cb),
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 cmsis_rtos_semaphore_cb *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 (attr->cb_mem != NULL) {
38 __ASSERT(attr->cb_size == sizeof(struct cmsis_rtos_semaphore_cb),
39 "Invalid cb_size\n");
40 semaphore = (struct cmsis_rtos_semaphore_cb *)attr->cb_mem;
41 } else if (k_mem_slab_alloc(&cmsis_rtos_semaphore_cb_slab, (void **)&semaphore,
42 K_MSEC(100)) != 0) {
43 return NULL;
44 }
45 (void)memset(semaphore, 0, sizeof(struct cmsis_rtos_semaphore_cb));
46 semaphore->is_cb_dynamic_allocation = attr->cb_mem == NULL;
47
48 k_sem_init(&semaphore->z_semaphore, initial_count, max_count);
49
50 if (attr->name == NULL) {
51 strncpy(semaphore->name, init_sema_attrs.name, sizeof(semaphore->name) - 1);
52 } else {
53 strncpy(semaphore->name, attr->name, sizeof(semaphore->name) - 1);
54 }
55
56 return (osSemaphoreId_t)semaphore;
57 }
58
59 /**
60 * @brief Wait until a semaphore becomes available.
61 */
osSemaphoreAcquire(osSemaphoreId_t semaphore_id,uint32_t timeout)62 osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout)
63 {
64 struct cmsis_rtos_semaphore_cb *semaphore = (struct cmsis_rtos_semaphore_cb *)semaphore_id;
65 int status;
66
67 if (semaphore_id == NULL) {
68 return osErrorParameter;
69 }
70
71 /* Can be called from ISRs only if timeout is set to 0 */
72 if (timeout > 0 && k_is_in_isr()) {
73 return osErrorParameter;
74 }
75
76 if (timeout == osWaitForever) {
77 status = k_sem_take(&semaphore->z_semaphore, K_FOREVER);
78 } else if (timeout == 0U) {
79 status = k_sem_take(&semaphore->z_semaphore, K_NO_WAIT);
80 } else {
81 status = k_sem_take(&semaphore->z_semaphore, K_TICKS(timeout));
82 }
83
84 if (status == -EBUSY) {
85 return osErrorResource;
86 } else if (status == -EAGAIN) {
87 return osErrorTimeout;
88 } else {
89 return osOK;
90 }
91 }
92
osSemaphoreGetCount(osSemaphoreId_t semaphore_id)93 uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id)
94 {
95 struct cmsis_rtos_semaphore_cb *semaphore = (struct cmsis_rtos_semaphore_cb *)semaphore_id;
96
97 if (semaphore_id == NULL) {
98 return 0;
99 }
100
101 return k_sem_count_get(&semaphore->z_semaphore);
102 }
103
104 /**
105 * @brief Release a semaphore that was obtained by osSemaphoreWait.
106 */
osSemaphoreRelease(osSemaphoreId_t semaphore_id)107 osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id)
108 {
109 struct cmsis_rtos_semaphore_cb *semaphore = (struct cmsis_rtos_semaphore_cb *)semaphore_id;
110
111 if (semaphore_id == NULL) {
112 return osErrorParameter;
113 }
114
115 /* All tokens have already been released */
116 if (k_sem_count_get(&semaphore->z_semaphore) == 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 cmsis_rtos_semaphore_cb *semaphore = (struct cmsis_rtos_semaphore_cb *)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 if (semaphore->is_cb_dynamic_allocation) {
145 k_mem_slab_free(&cmsis_rtos_semaphore_cb_slab, (void *)semaphore);
146 }
147
148 return osOK;
149 }
150
osSemaphoreGetName(osSemaphoreId_t semaphore_id)151 const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id)
152 {
153 struct cmsis_rtos_semaphore_cb *semaphore = (struct cmsis_rtos_semaphore_cb *)semaphore_id;
154
155 if (!k_is_in_isr() && (semaphore_id != NULL)) {
156 return semaphore->name;
157 } else {
158 return NULL;
159 }
160 }
161