Skip to content

Commit

Permalink
lib/cmsis_rtos_v2: Implement support for mempool APIs
Browse files Browse the repository at this point in the history
These APIs allow creating, allocating and freeing of mempools.

Note: "Mempool" in CMSIS actually means memslabs in Zephyr.

Signed-off-by: Rajavardhan Gundi <[email protected]>
  • Loading branch information
rgundi authored and carlescufi committed Dec 20, 2018
1 parent c58733c commit e5c8488
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/cmsis_rtos_v2/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(
timer.c
mutex.c
semaphore.c
mempool.c
)

zephyr_library_link_libraries(CMSIS)
Expand Down
7 changes: 7 additions & 0 deletions lib/cmsis_rtos_v2/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,11 @@ config CMSIS_V2_SEMAPHORE_MAX_COUNT
range 0 255
help
Mention max number of semaphores in CMSIS RTOS V2 compliant application.

config CMSIS_V2_MEM_SLAB_MAX_COUNT
int "Maximum mem slab count in CMSIS RTOS V2 application"
default 5
range 0 255
help
Mention maximum number of memory slabs in CMSIS RTOS V2 compliant application.
endif
213 changes: 213 additions & 0 deletions lib/cmsis_rtos_v2/mempool.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <kernel_structs.h>
#include "wrapper.h"

#define TIME_OUT_TICKS 10

K_MEM_SLAB_DEFINE(cv2_mem_slab, sizeof(struct cv2_mslab),
CONFIG_CMSIS_V2_MEM_SLAB_MAX_COUNT, 4);

static const osMemoryPoolAttr_t init_mslab_attrs = {
.name = "ZephyrMemPool",
.attr_bits = 0,
.cb_mem = NULL,
.cb_size = 0,
.mp_mem = NULL,
.mp_size = 0,
};

/**
* @brief Create and Initialize a memory pool.
*/
osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size,
const osMemoryPoolAttr_t *attr)
{
struct cv2_mslab *mslab;

if (k_is_in_isr()) {
return NULL;
}

if (attr == NULL) {
attr = &init_mslab_attrs;
}

/* This implementation requires memory to be allocated by the
* App layer
*/
if ((attr->mp_mem == NULL) ||
(attr->mp_size < block_count*block_size)) {
return NULL;
}

if (k_mem_slab_alloc(&cv2_mem_slab, (void **)&mslab, 100) == 0) {
(void)memset(mslab, 0, sizeof(struct cv2_mslab));
} else {
return NULL;
}

k_mem_slab_init(&mslab->z_mslab, attr->mp_mem, block_size, block_count);
memcpy(mslab->name, attr->name, 16);

return (osMemoryPoolId_t)mslab;
}

/**
* @brief Allocate a memory block from a memory pool.
*/
void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;
int retval;
void *ptr;

if (mslab == NULL) {
return NULL;
}

/* Can be called from ISRs only if timeout is set to 0 */
if (timeout > 0 && k_is_in_isr()) {
return NULL;
}

if (timeout == 0) {
retval = k_mem_slab_alloc(
(struct k_mem_slab *)(&mslab->z_mslab),
(void **)&ptr, K_NO_WAIT);
} else if (timeout == osWaitForever) {
retval = k_mem_slab_alloc(
(struct k_mem_slab *)(&mslab->z_mslab),
(void **)&ptr, K_FOREVER);
} else {
retval = k_mem_slab_alloc(
(struct k_mem_slab *)(&mslab->z_mslab),
(void **)&ptr, __ticks_to_ms(timeout));
}

if (retval == 0) {
return ptr;
} else {
return NULL;
}
}

/**
* @brief Return an allocated memory block back to a specific memory pool.
*/
osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (mslab == NULL) {
return osErrorParameter;
}

/* Note: Below error code is not supported.
* osErrorResource: the memory pool specified by parameter mp_id
* is in an invalid memory pool state.
*/

k_mem_slab_free((struct k_mem_slab *)(&mslab->z_mslab), (void *)&block);

return osOK;
}

/**
* @brief Get name of a Memory Pool object.
*/
const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (!k_is_in_isr() && (mslab != NULL)) {
return mslab->name;
} else {
return NULL;
}
}

/**
* @brief Get maximum number of memory blocks in a Memory Pool.
*/
uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (mslab == NULL) {
return 0;
} else {
return mslab->z_mslab.num_blocks;
}
}

/**
* @brief Get memory block size in a Memory Pool.
*/
uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (mslab == NULL) {
return 0;
} else {
return mslab->z_mslab.block_size;
}
}

/**
* @brief Get number of memory blocks used in a Memory Pool.
*/
uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (mslab == NULL) {
return 0;
} else {
return k_mem_slab_num_used_get(&mslab->z_mslab);
}
}

/**
* @brief Get number of memory blocks available in a Memory Pool.
*/
uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (mslab == NULL) {
return 0;
} else {
return k_mem_slab_num_free_get(&mslab->z_mslab);
}
}

/**
* @brief Delete a Memory Pool object.
*/
osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id)
{
struct cv2_mslab *mslab = (struct cv2_mslab *)mp_id;

if (mslab == NULL) {
return osErrorParameter;
}

if (k_is_in_isr()) {
return osErrorISR;
}

/* The status code "osErrorResource" (the memory pool specified by
* parameter mp_id is in an invalid memory pool state) is not
* supported in Zephyr.
*/

k_mem_slab_free(&cv2_mem_slab, (void *)&mslab);

return osOK;
}
5 changes: 5 additions & 0 deletions lib/cmsis_rtos_v2/wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ struct cv2_sem {
char name[16];
};

struct cv2_mslab {
struct k_mem_slab z_mslab;
char name[16];
};

extern osThreadId_t get_cmsis_thread_id(k_tid_t tid);
extern void *is_cmsis_rtos_v2_thread(void *thread_id);

Expand Down

0 comments on commit e5c8488

Please sign in to comment.