diff --git a/kernel/core/include/tos_kerr.h b/kernel/core/include/tos_kerr.h index e0cefe2b..91cf8be7 100644 --- a/kernel/core/include/tos_kerr.h +++ b/kernel/core/include/tos_kerr.h @@ -50,6 +50,8 @@ typedef enum k_err_en { K_ERR_MMBLK_POOL_EMPTY, K_ERR_MMBLK_INVALID_BLK_SIZE, K_ERR_MMBLK_INVALID_POOL_ADDR, + K_ERR_MMBLK_POOL_OUT_OF_MEMORY, + K_ERR_MMBLK_OUT_OF_MEMORY, K_ERR_MMHEAP_INVALID_POOL_ADDR = 800u, K_ERR_MMHEAP_INVALID_POOL_SIZE, diff --git a/kernel/core/include/tos_mmblk.h b/kernel/core/include/tos_mmblk.h index 2fd8f4de..aa4cbe60 100644 --- a/kernel/core/include/tos_mmblk.h +++ b/kernel/core/include/tos_mmblk.h @@ -67,6 +67,37 @@ __API__ k_err_t tos_mmblk_pool_create(k_mmblk_pool_t *mbp, void *pool_start, siz */ __API__ k_err_t tos_mmblk_pool_destroy(k_mmblk_pool_t *mbp); +/** + * @brief Create a dynamic memory manage block pool. + * Create a dynamic memory manage block pool. + * + * @attention None + * + * @param[in] mbp pointer to the pointer of memory block pool handler. + * @param[in] blk_num number of the blocks in the pool. + * @param[in] blk_size size of each block in the pool. + * + * @return errcode + * @retval #K_ERR_MMBLK_INVALID_POOL_ADDR start address of the pool is invalid. + * @retval #K_ERR_MMBLK_INVALID_BLK_SIZE size of the block is invalid. + * @retval #K_ERR_NONE return successfully. + */ +__API__ k_err_t tos_mmblk_pool_create_dyn(k_mmblk_pool_t **mbp, size_t blk_num, size_t blk_size); + +/** + * @brief Destroy a dynamic memory manage block pool. + * Destroy a memory dynamic manage block pool. + * + * @attention None + * + * @param[in] mbp pointer to the memory block pool handler. + * + * @return errcode + * @retval #K_ERR_OBJ_INVALID mbp is not a valid memory block pool handler. + * @retval #K_ERR_NONE return successfully. + */ +__API__ k_err_t tos_mmblk_pool_destroy_dyn(k_mmblk_pool_t *mbp); + /** * @brief Allocate a memory manage block. * Allocate a memory manage block. diff --git a/kernel/core/tos_mmblk.c b/kernel/core/tos_mmblk.c index 66e66c9b..dd7d3e8a 100644 --- a/kernel/core/tos_mmblk.c +++ b/kernel/core/tos_mmblk.c @@ -50,6 +50,8 @@ __API__ k_err_t tos_mmblk_pool_create(k_mmblk_pool_t *mbp, void *pool_start, siz mbp->blk_size = blk_size; TOS_OBJ_INIT(mbp, KNL_OBJ_TYPE_MMBLK_POOL); + + knl_object_alloc_set_static(&mbp->knl_obj); return K_ERR_NONE; } @@ -58,6 +60,12 @@ __API__ k_err_t tos_mmblk_pool_destroy(k_mmblk_pool_t *mbp) { TOS_PTR_SANITY_CHECK(mbp); TOS_OBJ_VERIFY(mbp, KNL_OBJ_TYPE_MMBLK_POOL); + +#if TOS_CFG_MMHEAP_EN > 0u + if (!knl_object_alloc_is_static(&mbp->knl_obj)) { + return K_ERR_OBJ_INVALID_ALLOC_TYPE; + } +#endif mbp->pool_start = K_NULL; mbp->free_list = K_NULL; @@ -70,6 +78,83 @@ __API__ k_err_t tos_mmblk_pool_destroy(k_mmblk_pool_t *mbp) return K_ERR_NONE; } +#if TOS_CFG_MMHEAP_EN > 0u + +__API__ k_err_t tos_mmblk_pool_create_dyn(k_mmblk_pool_t **mbp, size_t blk_num, size_t blk_size) +{ + uint32_t i; + void *pool_start; + k_mmblk_pool_t *the_mbp; + void *blk_curr, *blk_next; + + TOS_IN_IRQ_CHECK(); + TOS_PTR_SANITY_CHECK(mbp); + + if ((blk_size & K_MMBLK_ALIGN_MASK) != 0u) { + return K_ERR_MMBLK_INVALID_BLK_SIZE; + } + + the_mbp = tos_mmheap_calloc(1, sizeof(k_mmblk_pool_t)); + if (!the_mbp) { + return K_ERR_MMBLK_OUT_OF_MEMORY; + } + + pool_start = tos_mmheap_alloc(blk_num * blk_size); + if (!pool_start) { + return K_ERR_MMBLK_POOL_OUT_OF_MEMORY; + } + + blk_curr = pool_start; + blk_next = K_MMBLK_NEXT_BLK(blk_curr, blk_size); + + for (i = 0; i < blk_num - 1u; ++i) { + *(void **)blk_curr = blk_next; + blk_curr = blk_next; + blk_next = K_MMBLK_NEXT_BLK(blk_next, blk_size); + } + + *(void **)blk_curr = K_NULL; + + the_mbp->pool_start = pool_start; + the_mbp->free_list = pool_start; + the_mbp->blk_free = blk_num; + the_mbp->blk_max = blk_num; + the_mbp->blk_size = blk_size; + + TOS_OBJ_INIT(the_mbp, KNL_OBJ_TYPE_MMBLK_POOL); + + knl_object_alloc_set_dynamic(&the_mbp->knl_obj); + + *mbp = the_mbp; + + return K_ERR_NONE; +} + +__API__ k_err_t tos_mmblk_pool_destroy_dyn(k_mmblk_pool_t *mbp) +{ + TOS_PTR_SANITY_CHECK(mbp); + TOS_OBJ_VERIFY(mbp, KNL_OBJ_TYPE_MMBLK_POOL); + + if (!knl_object_alloc_is_dynamic(&mbp->knl_obj)) { + return K_ERR_OBJ_INVALID_ALLOC_TYPE; + } + + tos_mmheap_free(mbp->pool_start); + + mbp->pool_start = K_NULL; + mbp->free_list = K_NULL; + mbp->blk_free = 0; + mbp->blk_max = 0; + mbp->blk_size = 0; + + TOS_OBJ_DEINIT(mbp); + tos_mmheap_free(mbp); + + return K_ERR_NONE; +} + +#endif + __API__ k_err_t tos_mmblk_alloc(k_mmblk_pool_t *mbp, void **blk) { TOS_CPU_CPSR_ALLOC(); diff --git a/osal/cmsis_os/cmsis_os2.c b/osal/cmsis_os/cmsis_os2.c index 549bed7e..3890fb72 100644 --- a/osal/cmsis_os/cmsis_os2.c +++ b/osal/cmsis_os/cmsis_os2.c @@ -728,8 +728,11 @@ osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, if (attr->cb_mem) { err = tos_mmblk_pool_create((k_mmblk_pool_t*)attr->cb_mem, attr->mp_mem, block_count, block_size); - mpId = err == K_ERR_NONE ? attr->cb_mem : NULL; + mpId = (err == K_ERR_NONE) ? attr->cb_mem : NULL; } + } else { + err = tos_mmblk_pool_create_dyn(&mpId, block_count, block_size); + mpId = (err == K_ERR_NONE) ? mpId : NULL; } return (osMemoryPoolId_t)mpId; @@ -774,8 +777,12 @@ uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id) { } osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id) { k_mmblk_pool_t* mpId = (k_mmblk_pool_t*)mp_id; - - return errno_knl2cmsis(tos_mmblk_pool_destroy(mpId)); + + if (knl_object_alloc_is_dynamic(&mpId->knl_obj)) { + return errno_knl2cmsis(tos_mmblk_pool_destroy_dyn(mpId)); + } else { + return errno_knl2cmsis(tos_mmblk_pool_destroy(mpId)); + } } /*---------------------------------------------------------------------------*/ diff --git a/test/suit_mmblk.c b/test/suit_mmblk.c index 3b827f79..64274592 100644 --- a/test/suit_mmblk.c +++ b/test/suit_mmblk.c @@ -9,6 +9,9 @@ SUITE(suit_mmblk); k_mmblk_pool_t test_mmblk_pool_00; k_mmblk_pool_t test_mmblk_pool_01; k_mmblk_pool_t test_mmblk_pool_02; +k_mmblk_pool_t *test_mmblk_pool_dyn_00; +k_mmblk_pool_t *test_mmblk_pool_dyn_01; +k_mmblk_pool_t *test_mmblk_pool_dyn_02; uint8_t mmblk_pool_buffer_00[MMBLK_BLK_NUM * MMBLK_BLK_SIZE]; uint8_t mmblk_pool_buffer_01[MMBLK_BLK_NUM * MMBLK_BLK_SIZE]; @@ -69,6 +72,34 @@ TEST test_tos_mmblk_pool_destroy(void) PASS(); } +TEST test_tos_mmblk_pool_create_dyn(void) +{ + k_err_t err; + + err = tos_mmblk_pool_create_dyn(&test_mmblk_pool_dyn_00, MMBLK_BLK_NUM, MMBLK_BLK_SIZE); + ASSERT_EQ(err, K_ERR_NONE); + + err = tos_mmblk_pool_create_dyn(&test_mmblk_pool_dyn_01, MMBLK_BLK_NUM, MMBLK_BLK_SIZE); + ASSERT_EQ(err, K_ERR_NONE); + + err = tos_mmblk_pool_create_dyn(&test_mmblk_pool_dyn_02, MMBLK_BLK_NUM, MMBLK_BLK_SIZE); + ASSERT_EQ(err, K_ERR_NONE); + + err = tos_mmblk_pool_destroy_dyn(test_mmblk_pool_dyn_00); + ASSERT_EQ(err, K_ERR_NONE); + + err = tos_mmblk_pool_destroy_dyn(test_mmblk_pool_dyn_01); + ASSERT_EQ(err, K_ERR_NONE); + + err = tos_mmblk_pool_destroy_dyn(test_mmblk_pool_dyn_02); + ASSERT_EQ(err, K_ERR_NONE); + + err = tos_mmblk_pool_create_dyn(&test_mmblk_pool_dyn_00, MMBLK_BLK_NUM, MMBLK_BLK_SIZE + 1); + ASSERT_EQ(err, K_ERR_MMBLK_INVALID_BLK_SIZE); + + PASS(); +} + TEST test_tos_mmblk_alloc(void) { int i = 0; @@ -123,6 +154,7 @@ SUITE(suit_mmblk) { RUN_TEST(test_tos_mmblk_pool_create); RUN_TEST(test_tos_mmblk_pool_destroy); + RUN_TEST(test_tos_mmblk_pool_create_dyn); RUN_TEST(test_tos_mmblk_alloc); RUN_TEST(test_tos_mmblk_free); }