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 k_mem_slab_init(&mslab->z_mslab, mslab->pool, block_size, block_count);
72
73 if (attr->name == NULL) {
74 strncpy(mslab->name, init_mslab_attrs.name,
75 sizeof(mslab->name) - 1);
76 } else {
77 strncpy(mslab->name, attr->name, sizeof(mslab->name) - 1);
78 }
79
80 return (osMemoryPoolId_t)mslab;
81 }
82
83 /**
84 * @brief Allocate a memory block from a memory pool.
85 */
osMemoryPoolAlloc(osMemoryPoolId_t mp_id,uint32_t timeout)86 void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
87 {
88 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
89 int retval;
90 void *ptr;
91
92 if (mslab == NULL) {
93 return NULL;
94 }
95
96 /* Can be called from ISRs only if timeout is set to 0 */
97 if (timeout > 0 && k_is_in_isr()) {
98 return NULL;
99 }
100
101 if (timeout == 0U) {
102 retval = k_mem_slab_alloc(
103 (struct k_mem_slab *)(&mslab->z_mslab),
104 (void **)&ptr, K_NO_WAIT);
105 } else if (timeout == osWaitForever) {
106 retval = k_mem_slab_alloc(
107 (struct k_mem_slab *)(&mslab->z_mslab),
108 (void **)&ptr, K_FOREVER);
109 } else {
110 retval = k_mem_slab_alloc(
111 (struct k_mem_slab *)(&mslab->z_mslab),
112 (void **)&ptr, K_TICKS(timeout));
113 }
114
115 if (retval == 0) {
116 return ptr;
117 } else {
118 return NULL;
119 }
120 }
121
122 /**
123 * @brief Return an allocated memory block back to a specific memory pool.
124 */
osMemoryPoolFree(osMemoryPoolId_t mp_id,void * block)125 osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
126 {
127 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
128
129 if (mslab == NULL) {
130 return osErrorParameter;
131 }
132
133 /* Note: Below error code is not supported.
134 * osErrorResource: the memory pool specified by parameter mp_id
135 * is in an invalid memory pool state.
136 */
137
138 k_mem_slab_free((struct k_mem_slab *)(&mslab->z_mslab), (void *)&block);
139
140 return osOK;
141 }
142
143 /**
144 * @brief Get name of a Memory Pool object.
145 */
osMemoryPoolGetName(osMemoryPoolId_t mp_id)146 const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
147 {
148 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
149
150 if (!k_is_in_isr() && (mslab != NULL)) {
151 return mslab->name;
152 } else {
153 return NULL;
154 }
155 }
156
157 /**
158 * @brief Get maximum number of memory blocks in a Memory Pool.
159 */
osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)160 uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
161 {
162 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
163
164 if (mslab == NULL) {
165 return 0;
166 } else {
167 return mslab->z_mslab.num_blocks;
168 }
169 }
170
171 /**
172 * @brief Get memory block size in a Memory Pool.
173 */
osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)174 uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
175 {
176 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
177
178 if (mslab == NULL) {
179 return 0;
180 } else {
181 return mslab->z_mslab.block_size;
182 }
183 }
184
185 /**
186 * @brief Get number of memory blocks used in a Memory Pool.
187 */
osMemoryPoolGetCount(osMemoryPoolId_t mp_id)188 uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
189 {
190 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
191
192 if (mslab == NULL) {
193 return 0;
194 } else {
195 return k_mem_slab_num_used_get(&mslab->z_mslab);
196 }
197 }
198
199 /**
200 * @brief Get number of memory blocks available in a Memory Pool.
201 */
osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)202 uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
203 {
204 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
205
206 if (mslab == NULL) {
207 return 0;
208 } else {
209 return k_mem_slab_num_free_get(&mslab->z_mslab);
210 }
211 }
212
213 /**
214 * @brief Delete a Memory Pool object.
215 */
osMemoryPoolDelete(osMemoryPoolId_t mp_id)216 osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
217 {
218 struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
219
220 if (mslab == NULL) {
221 return osErrorParameter;
222 }
223
224 if (k_is_in_isr()) {
225 return osErrorISR;
226 }
227
228 /* The status code "osErrorResource" (the memory pool specified by
229 * parameter mp_id is in an invalid memory pool state) is not
230 * supported in Zephyr.
231 */
232
233 if (mslab->is_dynamic_allocation) {
234 k_free(mslab->pool);
235 }
236 k_mem_slab_free(&cv2_mem_slab, (void *)&mslab);
237
238 return osOK;
239 }
240