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 TIME_OUT_TICKS 10
12
13 K_MEM_SLAB_DEFINE(cv2_mem_slab, sizeof(struct cv2_mslab),
14 CONFIG_CMSIS_V2_MEM_SLAB_MAX_COUNT, 4);
15
16 static const osMemoryPoolAttr_t init_mslab_attrs = {
17 .name = "ZephyrMemPool",
18 .attr_bits = 0,
19 .cb_mem = NULL,
20 .cb_size = 0,
21 .mp_mem = NULL,
22 .mp_size = 0,
23 };
24
25 /**
26 * @brief Create and Initialize a memory pool.
27 */
osMemoryPoolNew(uint32_t block_count,uint32_t block_size,const osMemoryPoolAttr_t * attr)28 osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size,
29 const osMemoryPoolAttr_t *attr)
30 {
31 struct cv2_mslab *mslab;
32
33 BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE >=
34 CONFIG_CMSIS_V2_MEM_SLAB_MAX_DYNAMIC_SIZE,
35 "heap must be configured to be at least the max dynamic size");
36
37 if (k_is_in_isr()) {
38 return NULL;
39 }
40
41 if ((attr != NULL) && (attr->mp_size < block_count * block_size)) {
42 return NULL;
43 }
44
45 if (attr == NULL) {
46 attr = &init_mslab_attrs;
47 }
48
49 if (k_mem_slab_alloc(&cv2_mem_slab, (void **)&mslab, K_MSEC(100)) == 0) {
50 (void)memset(mslab, 0, sizeof(struct cv2_mslab));
51 } else {
52 return NULL;
53 }
54
55 if (attr->mp_mem == NULL) {
56 __ASSERT((block_count * block_size) <=
57 CONFIG_CMSIS_V2_MEM_SLAB_MAX_DYNAMIC_SIZE,
58 "memory slab/pool size exceeds dynamic maximum");
59
60 mslab->pool = k_calloc(block_count, block_size);
61 if (mslab->pool == NULL) {
62 k_mem_slab_free(&cv2_mem_slab, (void *)mslab);
63 return NULL;
64 }
65 mslab->is_dynamic_allocation = TRUE;
66 } else {
67 mslab->pool = attr->mp_mem;
68 mslab->is_dynamic_allocation = FALSE;
69 }
70
71 int rc = k_mem_slab_init(&mslab->z_mslab, mslab->pool, block_size, block_count);
72
73 if (rc != 0) {
74 k_mem_slab_free(&cv2_mem_slab, (void *)mslab);
75 if (attr->mp_mem == NULL) {
76 k_free(mslab->pool);
77 }
78 return NULL;
79 }
80
81 if (attr->name == NULL) {
82 strncpy(mslab->name, init_mslab_attrs.name,
83 sizeof(mslab->name) - 1);
84 } else {
85 strncpy(mslab->name, attr->name, sizeof(mslab->name) - 1);
86 }
87
88 return (osMemoryPoolId_t)mslab;
89 }
90
91 /**
92 * @brief Allocate a memory block from a memory pool.
93 */
osMemoryPoolAlloc(osMemoryPoolId_t mp_id,uint32_t timeout)94 void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
95 {
96 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
97 int retval;
98 void *ptr;
99
100 if (mslab == NULL) {
101 return NULL;
102 }
103
104 /* Can be called from ISRs only if timeout is set to 0 */
105 if (timeout > 0 && k_is_in_isr()) {
106 return NULL;
107 }
108
109 if (timeout == 0U) {
110 retval = k_mem_slab_alloc(
111 (struct k_mem_slab *)(&mslab->z_mslab),
112 (void **)&ptr, K_NO_WAIT);
113 } else if (timeout == osWaitForever) {
114 retval = k_mem_slab_alloc(
115 (struct k_mem_slab *)(&mslab->z_mslab),
116 (void **)&ptr, K_FOREVER);
117 } else {
118 retval = k_mem_slab_alloc(
119 (struct k_mem_slab *)(&mslab->z_mslab),
120 (void **)&ptr, K_TICKS(timeout));
121 }
122
123 if (retval == 0) {
124 return ptr;
125 } else {
126 return NULL;
127 }
128 }
129
130 /**
131 * @brief Return an allocated memory block back to a specific memory pool.
132 */
osMemoryPoolFree(osMemoryPoolId_t mp_id,void * block)133 osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
134 {
135 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
136
137 if (mslab == NULL) {
138 return osErrorParameter;
139 }
140
141 /* Note: Below error code is not supported.
142 * osErrorResource: the memory pool specified by parameter mp_id
143 * is in an invalid memory pool state.
144 */
145
146 k_mem_slab_free((struct k_mem_slab *)(&mslab->z_mslab), (void *)block);
147
148 return osOK;
149 }
150
151 /**
152 * @brief Get name of a Memory Pool object.
153 */
osMemoryPoolGetName(osMemoryPoolId_t mp_id)154 const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
155 {
156 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
157
158 if (!k_is_in_isr() && (mslab != NULL)) {
159 return mslab->name;
160 } else {
161 return NULL;
162 }
163 }
164
165 /**
166 * @brief Get maximum number of memory blocks in a Memory Pool.
167 */
osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)168 uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
169 {
170 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
171
172 if (mslab == NULL) {
173 return 0;
174 } else {
175 return mslab->z_mslab.info.num_blocks;
176 }
177 }
178
179 /**
180 * @brief Get memory block size in a Memory Pool.
181 */
osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)182 uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
183 {
184 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
185
186 if (mslab == NULL) {
187 return 0;
188 } else {
189 return mslab->z_mslab.info.block_size;
190 }
191 }
192
193 /**
194 * @brief Get number of memory blocks used in a Memory Pool.
195 */
osMemoryPoolGetCount(osMemoryPoolId_t mp_id)196 uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
197 {
198 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
199
200 if (mslab == NULL) {
201 return 0;
202 } else {
203 return k_mem_slab_num_used_get(&mslab->z_mslab);
204 }
205 }
206
207 /**
208 * @brief Get number of memory blocks available in a Memory Pool.
209 */
osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)210 uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
211 {
212 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
213
214 if (mslab == NULL) {
215 return 0;
216 } else {
217 return k_mem_slab_num_free_get(&mslab->z_mslab);
218 }
219 }
220
221 /**
222 * @brief Delete a Memory Pool object.
223 */
osMemoryPoolDelete(osMemoryPoolId_t mp_id)224 osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
225 {
226 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
227
228 if (mslab == NULL) {
229 return osErrorParameter;
230 }
231
232 if (k_is_in_isr()) {
233 return osErrorISR;
234 }
235
236 /* The status code "osErrorResource" (the memory pool specified by
237 * parameter mp_id is in an invalid memory pool state) is not
238 * supported in Zephyr.
239 */
240
241 if (mslab->is_dynamic_allocation) {
242 k_free(mslab->pool);
243 }
244 k_mem_slab_free(&cv2_mem_slab, (void *)mslab);
245
246 return osOK;
247 }
248