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