706 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			706 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2013-2018 Arm Limited. All rights reserved.
 | |
|  *
 | |
|  * SPDX-License-Identifier: Apache-2.0
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the License); you may
 | |
|  * not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  * www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 | |
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  *
 | |
|  * -----------------------------------------------------------------------------
 | |
|  *
 | |
|  * Project:     CMSIS-RTOS RTX
 | |
|  * Title:       Memory Pool functions
 | |
|  *
 | |
|  * -----------------------------------------------------------------------------
 | |
|  */
 | |
| 
 | |
| #include "rtx_lib.h"
 | |
| 
 | |
| 
 | |
| //  OS Runtime Object Memory Usage
 | |
| #if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)))
 | |
| osRtxObjectMemUsage_t osRtxMemoryPoolMemUsage \
 | |
| __attribute__((section(".data.os.mempool.obj"))) =
 | |
| { 0U, 0U, 0U };
 | |
| #endif
 | |
| 
 | |
| 
 | |
| //  ==== Library functions ====
 | |
| 
 | |
| /// Initialize Memory Pool.
 | |
| /// \param[in]  mp_info         memory pool info.
 | |
| /// \param[in]  block_count     maximum number of memory blocks in memory pool.
 | |
| /// \param[in]  block_size      size of a memory block in bytes.
 | |
| /// \param[in]  block_mem       pointer to memory for block storage.
 | |
| /// \return 1 - success, 0 - failure.
 | |
| uint32_t osRtxMemoryPoolInit (os_mp_info_t *mp_info, uint32_t block_count, uint32_t block_size, void *block_mem) {
 | |
|   //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
 | |
|   void *mem;
 | |
|   void *block;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp_info == NULL) || (block_count == 0U) || (block_size  == 0U) || (block_mem  == NULL)) {
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return 0U;
 | |
|   }
 | |
| 
 | |
|   // Initialize information structure
 | |
|   mp_info->max_blocks  = block_count;
 | |
|   mp_info->used_blocks = 0U;
 | |
|   mp_info->block_size  = block_size;
 | |
|   mp_info->block_base  = block_mem;
 | |
|   mp_info->block_free  = block_mem;
 | |
|   mp_info->block_lim   = &(((uint8_t *)block_mem)[block_count * block_size]);
 | |
| 
 | |
|   EvrRtxMemoryBlockInit(mp_info, block_count, block_size, block_mem);
 | |
| 
 | |
|   // Link all free blocks
 | |
|   mem = block_mem;
 | |
|   while (--block_count != 0U) {
 | |
|     block = &((uint8_t *)mem)[block_size];
 | |
|     *((void **)mem) = block;
 | |
|     mem = block;
 | |
|   }
 | |
|   *((void **)mem) = NULL;
 | |
| 
 | |
|   return 1U;
 | |
| }
 | |
| 
 | |
| /// Allocate a memory block from a Memory Pool.
 | |
| /// \param[in]  mp_info         memory pool info.
 | |
| /// \return address of the allocated memory block or NULL in case of no memory is available.
 | |
| void *osRtxMemoryPoolAlloc (os_mp_info_t *mp_info) {
 | |
| #if (EXCLUSIVE_ACCESS == 0)
 | |
|   uint32_t primask = __get_PRIMASK();
 | |
| #endif
 | |
|   void *block;
 | |
| 
 | |
|   if (mp_info == NULL) {
 | |
|     EvrRtxMemoryBlockAlloc(NULL, NULL);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
| #if (EXCLUSIVE_ACCESS == 0)
 | |
|   __disable_irq();
 | |
| 
 | |
|   block = mp_info->block_free;
 | |
|   if (block != NULL) {
 | |
|     //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
 | |
|     mp_info->block_free = *((void **)block);
 | |
|     mp_info->used_blocks++;
 | |
|   }
 | |
| 
 | |
|   if (primask == 0U) {
 | |
|     __enable_irq();
 | |
|   }
 | |
| #else
 | |
|   block = atomic_link_get(&mp_info->block_free);
 | |
|   if (block != NULL) {
 | |
|     (void)atomic_inc32(&mp_info->used_blocks);
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   EvrRtxMemoryBlockAlloc(mp_info, block);
 | |
| 
 | |
|   return block;
 | |
| }
 | |
| 
 | |
| /// Return an allocated memory block back to a Memory Pool.
 | |
| /// \param[in]  mp_info         memory pool info.
 | |
| /// \param[in]  block           address of the allocated memory block to be returned to the memory pool.
 | |
| /// \return status code that indicates the execution status of the function.
 | |
| osStatus_t osRtxMemoryPoolFree (os_mp_info_t *mp_info, void *block) {
 | |
| #if (EXCLUSIVE_ACCESS == 0)
 | |
|   uint32_t primask = __get_PRIMASK();
 | |
| #endif
 | |
| 
 | |
|   //lint -e{946} "Relational operator applied to pointers"
 | |
|   if ((mp_info == NULL) || (block < mp_info->block_base) || (block >= mp_info->block_lim)) {
 | |
|     EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return osErrorParameter;
 | |
|   }
 | |
| 
 | |
| #if (EXCLUSIVE_ACCESS == 0)
 | |
|   __disable_irq();
 | |
| 
 | |
|   //lint --e{9079} --e{9087} "conversion from pointer to void to pointer to other type"
 | |
|   *((void **)block) = mp_info->block_free;
 | |
|   mp_info->block_free = block;
 | |
|   mp_info->used_blocks--;
 | |
| 
 | |
|   if (primask == 0U) {
 | |
|     __enable_irq();
 | |
|   }
 | |
| #else
 | |
|   atomic_link_put(&mp_info->block_free, block);
 | |
|   (void)atomic_dec32(&mp_info->used_blocks);
 | |
| #endif
 | |
| 
 | |
|   EvrRtxMemoryBlockFree(mp_info, block, (int32_t)osOK);
 | |
| 
 | |
|   return osOK;
 | |
| }
 | |
| 
 | |
| 
 | |
| //  ==== Post ISR processing ====
 | |
| 
 | |
| /// Memory Pool post ISR processing.
 | |
| /// \param[in]  mp              memory pool object.
 | |
| static void osRtxMemoryPoolPostProcess (os_memory_pool_t *mp) {
 | |
|   void        *block;
 | |
|   os_thread_t *thread;
 | |
| 
 | |
|   // Check if Thread is waiting to allocate memory
 | |
|   if (mp->thread_list != NULL) {
 | |
|     // Allocate memory
 | |
|     block = osRtxMemoryPoolAlloc(&mp->mp_info);
 | |
|     if (block != NULL) {
 | |
|       // Wakeup waiting Thread with highest Priority
 | |
|       thread = osRtxThreadListGet(osRtxObject(mp));
 | |
|       //lint -e{923} "cast from pointer to unsigned int"
 | |
|       osRtxThreadWaitExit(thread, (uint32_t)block, FALSE);
 | |
|       EvrRtxMemoryPoolAllocated(mp, block);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| //  ==== Service Calls ====
 | |
| 
 | |
| /// Create and Initialize a Memory Pool object.
 | |
| /// \note API identical to osMemoryPoolNew
 | |
| static osMemoryPoolId_t svcRtxMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
 | |
|   os_memory_pool_t *mp;
 | |
|   void             *mp_mem;
 | |
|   uint32_t          mp_size;
 | |
|   uint32_t          b_count;
 | |
|   uint32_t          b_size;
 | |
|   uint32_t          size;
 | |
|   uint8_t           flags;
 | |
|   const char       *name;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((block_count == 0U) || (block_size  == 0U)) {
 | |
|     EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return NULL;
 | |
|   }
 | |
|   b_count =  block_count;
 | |
|   b_size  = (block_size + 3U) & ~3UL;
 | |
|   if ((__CLZ(b_count) + __CLZ(b_size)) < 32U) {
 | |
|     EvrRtxMemoryPoolError(NULL, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   size = b_count * b_size;
 | |
| 
 | |
|   // Process attributes
 | |
|   if (attr != NULL) {
 | |
|     name    = attr->name;
 | |
|     //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
 | |
|     mp      = attr->cb_mem;
 | |
|     //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
 | |
|     mp_mem  = attr->mp_mem;
 | |
|     mp_size = attr->mp_size;
 | |
|     if (mp != NULL) {
 | |
|       //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
 | |
|       if ((((uint32_t)mp & 3U) != 0U) || (attr->cb_size < sizeof(os_memory_pool_t))) {
 | |
|         EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
 | |
|         //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|         return NULL;
 | |
|       }
 | |
|     } else {
 | |
|       if (attr->cb_size != 0U) {
 | |
|         EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidControlBlock);
 | |
|         //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|         return NULL;
 | |
|       }
 | |
|     }
 | |
|     if (mp_mem != NULL) {
 | |
|       //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
 | |
|       if ((((uint32_t)mp_mem & 3U) != 0U) || (mp_size < size)) {
 | |
|         EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
 | |
|         //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|         return NULL;
 | |
|       }
 | |
|     } else {
 | |
|       if (mp_size != 0U) {
 | |
|         EvrRtxMemoryPoolError(NULL, osRtxErrorInvalidDataMemory);
 | |
|         //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|         return NULL;
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     name   = NULL;
 | |
|     mp     = NULL;
 | |
|     mp_mem = NULL;
 | |
|   }
 | |
| 
 | |
|   // Allocate object memory if not provided
 | |
|   if (mp == NULL) {
 | |
|     if (osRtxInfo.mpi.memory_pool != NULL) {
 | |
|       //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
 | |
|       mp = osRtxMemoryPoolAlloc(osRtxInfo.mpi.memory_pool);
 | |
|     } else {
 | |
|       //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
 | |
|       mp = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_memory_pool_t), 1U);
 | |
|     }
 | |
| #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
 | |
|     if (mp != NULL) {
 | |
|       uint32_t used;
 | |
|       osRtxMemoryPoolMemUsage.cnt_alloc++;
 | |
|       used = osRtxMemoryPoolMemUsage.cnt_alloc - osRtxMemoryPoolMemUsage.cnt_free;
 | |
|       if (osRtxMemoryPoolMemUsage.max_used < used) {
 | |
|         osRtxMemoryPoolMemUsage.max_used = used;
 | |
|       }
 | |
|     }
 | |
| #endif
 | |
|     flags = osRtxFlagSystemObject;
 | |
|   } else {
 | |
|     flags = 0U;
 | |
|   }
 | |
| 
 | |
|   // Allocate data memory if not provided
 | |
|   if ((mp != NULL) && (mp_mem == NULL)) {
 | |
|     //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
 | |
|     mp_mem = osRtxMemoryAlloc(osRtxInfo.mem.mp_data, size, 0U);
 | |
|     if (mp_mem == NULL) {
 | |
|       if ((flags & osRtxFlagSystemObject) != 0U) {
 | |
|         if (osRtxInfo.mpi.memory_pool != NULL) {
 | |
|           (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
 | |
|         } else {
 | |
|           (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
 | |
|         }
 | |
| #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
 | |
|         osRtxMemoryPoolMemUsage.cnt_free++;
 | |
| #endif
 | |
|       }
 | |
|       mp = NULL;
 | |
|     } else {
 | |
|       memset(mp_mem, 0, size);
 | |
|     }
 | |
|     flags |= osRtxFlagSystemMemory;
 | |
|   }
 | |
| 
 | |
|   if (mp != NULL) {
 | |
|     // Initialize control block
 | |
|     mp->id          = osRtxIdMemoryPool;
 | |
|     mp->flags       = flags;
 | |
|     mp->name        = name;
 | |
|     mp->thread_list = NULL;
 | |
|     (void)osRtxMemoryPoolInit(&mp->mp_info, b_count, b_size, mp_mem);
 | |
| 
 | |
|     // Register post ISR processing function
 | |
|     osRtxInfo.post_process.memory_pool = osRtxMemoryPoolPostProcess;
 | |
| 
 | |
|     EvrRtxMemoryPoolCreated(mp, mp->name);
 | |
|   } else {
 | |
|     EvrRtxMemoryPoolError(NULL, (int32_t)osErrorNoMemory);
 | |
|   }
 | |
| 
 | |
|   return mp;
 | |
| }
 | |
| 
 | |
| /// Get name of a Memory Pool object.
 | |
| /// \note API identical to osMemoryPoolGetName
 | |
| static const char *svcRtxMemoryPoolGetName (osMemoryPoolId_t mp_id) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolGetName(mp, NULL);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   EvrRtxMemoryPoolGetName(mp, mp->name);
 | |
| 
 | |
|   return mp->name;
 | |
| }
 | |
| 
 | |
| /// Allocate a memory block from a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolAlloc
 | |
| static void *svcRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
|   void             *block;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   // Allocate memory
 | |
|   block = osRtxMemoryPoolAlloc(&mp->mp_info);
 | |
|   if (block != NULL) {
 | |
|     EvrRtxMemoryPoolAllocated(mp, block);
 | |
|   } else {
 | |
|     // No memory available
 | |
|     if (timeout != 0U) {
 | |
|       EvrRtxMemoryPoolAllocPending(mp, timeout);
 | |
|       // Suspend current Thread
 | |
|       if (osRtxThreadWaitEnter(osRtxThreadWaitingMemoryPool, timeout)) {
 | |
|         osRtxThreadListPut(osRtxObject(mp), osRtxThreadGetRunning());
 | |
|       } else {
 | |
|         EvrRtxMemoryPoolAllocTimeout(mp);
 | |
|       }
 | |
|     } else {
 | |
|       EvrRtxMemoryPoolAllocFailed(mp);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return block;
 | |
| }
 | |
| 
 | |
| /// Return an allocated memory block back to a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolFree
 | |
| static osStatus_t svcRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
|   void             *block0;
 | |
|   os_thread_t      *thread;
 | |
|   osStatus_t        status;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return osErrorParameter;
 | |
|   }
 | |
| 
 | |
|   // Free memory
 | |
|   status = osRtxMemoryPoolFree(&mp->mp_info, block);
 | |
|   if (status == osOK) {
 | |
|     EvrRtxMemoryPoolDeallocated(mp, block);
 | |
|     // Check if Thread is waiting to allocate memory
 | |
|     if (mp->thread_list != NULL) {
 | |
|       // Allocate memory
 | |
|       block0 = osRtxMemoryPoolAlloc(&mp->mp_info);
 | |
|       if (block0 != NULL) {
 | |
|         // Wakeup waiting Thread with highest Priority
 | |
|         thread = osRtxThreadListGet(osRtxObject(mp));
 | |
|         //lint -e{923} "cast from pointer to unsigned int"
 | |
|         osRtxThreadWaitExit(thread, (uint32_t)block0, TRUE);
 | |
|         EvrRtxMemoryPoolAllocated(mp, block0);
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     EvrRtxMemoryPoolFreeFailed(mp, block);
 | |
|   }
 | |
| 
 | |
|   return status;
 | |
| }
 | |
| 
 | |
| /// Get maximum number of memory blocks in a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolGetCapacity
 | |
| static uint32_t svcRtxMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolGetCapacity(mp, 0U);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return 0U;
 | |
|   }
 | |
| 
 | |
|   EvrRtxMemoryPoolGetCapacity(mp, mp->mp_info.max_blocks);
 | |
| 
 | |
|   return mp->mp_info.max_blocks;
 | |
| }
 | |
| 
 | |
| /// Get memory block size in a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolGetBlockSize
 | |
| static uint32_t svcRtxMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolGetBlockSize(mp, 0U);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return 0U;
 | |
|   }
 | |
| 
 | |
|   EvrRtxMemoryPoolGetBlockSize(mp, mp->mp_info.block_size);
 | |
| 
 | |
|   return mp->mp_info.block_size;
 | |
| }
 | |
| 
 | |
| /// Get number of memory blocks used in a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolGetCount
 | |
| static uint32_t svcRtxMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolGetCount(mp, 0U);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return 0U;
 | |
|   }
 | |
| 
 | |
|   EvrRtxMemoryPoolGetCount(mp, mp->mp_info.used_blocks);
 | |
| 
 | |
|   return mp->mp_info.used_blocks;
 | |
| }
 | |
| 
 | |
| /// Get number of memory blocks available in a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolGetSpace
 | |
| static uint32_t svcRtxMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolGetSpace(mp, 0U);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return 0U;
 | |
|   }
 | |
| 
 | |
|   EvrRtxMemoryPoolGetSpace(mp, mp->mp_info.max_blocks - mp->mp_info.used_blocks);
 | |
| 
 | |
|   return (mp->mp_info.max_blocks - mp->mp_info.used_blocks);
 | |
| }
 | |
| 
 | |
| /// Delete a Memory Pool object.
 | |
| /// \note API identical to osMemoryPoolDelete
 | |
| static osStatus_t svcRtxMemoryPoolDelete (osMemoryPoolId_t mp_id) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
|   os_thread_t      *thread;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return osErrorParameter;
 | |
|   }
 | |
| 
 | |
|   // Unblock waiting threads
 | |
|   if (mp->thread_list != NULL) {
 | |
|     do {
 | |
|       thread = osRtxThreadListGet(osRtxObject(mp));
 | |
|       osRtxThreadWaitExit(thread, 0U, FALSE);
 | |
|     } while (mp->thread_list != NULL);
 | |
|     osRtxThreadDispatch(NULL);
 | |
|   }
 | |
| 
 | |
|   // Mark object as invalid
 | |
|   mp->id = osRtxIdInvalid;
 | |
| 
 | |
|   // Free data memory
 | |
|   if ((mp->flags & osRtxFlagSystemMemory) != 0U) {
 | |
|     (void)osRtxMemoryFree(osRtxInfo.mem.mp_data, mp->mp_info.block_base);
 | |
|   }
 | |
| 
 | |
|   // Free object memory
 | |
|   if ((mp->flags & osRtxFlagSystemObject) != 0U) {
 | |
|     if (osRtxInfo.mpi.memory_pool != NULL) {
 | |
|       (void)osRtxMemoryPoolFree(osRtxInfo.mpi.memory_pool, mp);
 | |
|     } else {
 | |
|       (void)osRtxMemoryFree(osRtxInfo.mem.common, mp);
 | |
|     }
 | |
| #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
 | |
|     osRtxMemoryPoolMemUsage.cnt_free++;
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   EvrRtxMemoryPoolDestroyed(mp);
 | |
| 
 | |
|   return osOK;
 | |
| }
 | |
| 
 | |
| //  Service Calls definitions
 | |
| //lint ++flb "Library Begin" [MISRA Note 11]
 | |
| SVC0_3(MemoryPoolNew,          osMemoryPoolId_t, uint32_t, uint32_t, const osMemoryPoolAttr_t *)
 | |
| SVC0_1(MemoryPoolGetName,      const char *,     osMemoryPoolId_t)
 | |
| SVC0_2(MemoryPoolAlloc,        void *,           osMemoryPoolId_t, uint32_t)
 | |
| SVC0_2(MemoryPoolFree,         osStatus_t,       osMemoryPoolId_t, void *)
 | |
| SVC0_1(MemoryPoolGetCapacity,  uint32_t,         osMemoryPoolId_t)
 | |
| SVC0_1(MemoryPoolGetBlockSize, uint32_t,         osMemoryPoolId_t)
 | |
| SVC0_1(MemoryPoolGetCount,     uint32_t,         osMemoryPoolId_t)
 | |
| SVC0_1(MemoryPoolGetSpace,     uint32_t,         osMemoryPoolId_t)
 | |
| SVC0_1(MemoryPoolDelete,       osStatus_t,       osMemoryPoolId_t)
 | |
| //lint --flb "Library End"
 | |
| 
 | |
| 
 | |
| //  ==== ISR Calls ====
 | |
| 
 | |
| /// Allocate a memory block from a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolAlloc
 | |
| __STATIC_INLINE
 | |
| void *isrRtxMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
|   void             *block;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool) || (timeout != 0U)) {
 | |
|     EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   // Allocate memory
 | |
|   block = osRtxMemoryPoolAlloc(&mp->mp_info);
 | |
|   if (block == NULL) {
 | |
|     EvrRtxMemoryPoolAllocFailed(mp);
 | |
|   } else {
 | |
|     EvrRtxMemoryPoolAllocated(mp, block);
 | |
|   }
 | |
| 
 | |
|   return block;
 | |
| }
 | |
| 
 | |
| /// Return an allocated memory block back to a Memory Pool.
 | |
| /// \note API identical to osMemoryPoolFree
 | |
| __STATIC_INLINE
 | |
| osStatus_t isrRtxMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
 | |
|   os_memory_pool_t *mp = osRtxMemoryPoolId(mp_id);
 | |
|   osStatus_t        status;
 | |
| 
 | |
|   // Check parameters
 | |
|   if ((mp == NULL) || (mp->id != osRtxIdMemoryPool)) {
 | |
|     EvrRtxMemoryPoolError(mp, (int32_t)osErrorParameter);
 | |
|     //lint -e{904} "Return statement before end of function" [MISRA Note 1]
 | |
|     return osErrorParameter;
 | |
|   }
 | |
| 
 | |
|   // Free memory
 | |
|   status = osRtxMemoryPoolFree(&mp->mp_info, block);
 | |
|   if (status == osOK) {
 | |
|     // Register post ISR processing
 | |
|     osRtxPostProcess(osRtxObject(mp));
 | |
|     EvrRtxMemoryPoolDeallocated(mp, block);
 | |
|   } else {
 | |
|     EvrRtxMemoryPoolFreeFailed(mp, block);
 | |
|   }
 | |
| 
 | |
|   return status;
 | |
| }
 | |
| 
 | |
| 
 | |
| //  ==== Public API ====
 | |
| 
 | |
| /// Create and Initialize a Memory Pool object.
 | |
| osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) {
 | |
|   osMemoryPoolId_t mp_id;
 | |
| 
 | |
|   EvrRtxMemoryPoolNew(block_count, block_size, attr);
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     EvrRtxMemoryPoolError(NULL, (int32_t)osErrorISR);
 | |
|     mp_id = NULL;
 | |
|   } else {
 | |
|     mp_id = __svcMemoryPoolNew(block_count, block_size, attr);
 | |
|   }
 | |
|   return mp_id;
 | |
| }
 | |
| 
 | |
| /// Get name of a Memory Pool object.
 | |
| const char *osMemoryPoolGetName (osMemoryPoolId_t mp_id) {
 | |
|   const char *name;
 | |
| 
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     EvrRtxMemoryPoolGetName(mp_id, NULL);
 | |
|     name = NULL;
 | |
|   } else {
 | |
|     name = __svcMemoryPoolGetName(mp_id);
 | |
|   }
 | |
|   return name;
 | |
| }
 | |
| 
 | |
| /// Allocate a memory block from a Memory Pool.
 | |
| void *osMemoryPoolAlloc (osMemoryPoolId_t mp_id, uint32_t timeout) {
 | |
|   void *memory;
 | |
| 
 | |
|   EvrRtxMemoryPoolAlloc(mp_id, timeout);
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     memory = isrRtxMemoryPoolAlloc(mp_id, timeout);
 | |
|   } else {
 | |
|     memory =  __svcMemoryPoolAlloc(mp_id, timeout);
 | |
|   }
 | |
|   return memory;
 | |
| }
 | |
| 
 | |
| /// Return an allocated memory block back to a Memory Pool.
 | |
| osStatus_t osMemoryPoolFree (osMemoryPoolId_t mp_id, void *block) {
 | |
|   osStatus_t status;
 | |
| 
 | |
|   EvrRtxMemoryPoolFree(mp_id, block);
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     status = isrRtxMemoryPoolFree(mp_id, block);
 | |
|   } else {
 | |
|     status =  __svcMemoryPoolFree(mp_id, block);
 | |
|   }
 | |
|   return status;
 | |
| }
 | |
| 
 | |
| /// Get maximum number of memory blocks in a Memory Pool.
 | |
| uint32_t osMemoryPoolGetCapacity (osMemoryPoolId_t mp_id) {
 | |
|   uint32_t capacity;
 | |
| 
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     capacity = svcRtxMemoryPoolGetCapacity(mp_id);
 | |
|   } else {
 | |
|     capacity =  __svcMemoryPoolGetCapacity(mp_id);
 | |
|   }
 | |
|   return capacity;
 | |
| }
 | |
| 
 | |
| /// Get memory block size in a Memory Pool.
 | |
| uint32_t osMemoryPoolGetBlockSize (osMemoryPoolId_t mp_id) {
 | |
|   uint32_t block_size;
 | |
| 
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     block_size = svcRtxMemoryPoolGetBlockSize(mp_id);
 | |
|   } else {
 | |
|     block_size =  __svcMemoryPoolGetBlockSize(mp_id);
 | |
|   }
 | |
|   return block_size;
 | |
| }
 | |
| 
 | |
| /// Get number of memory blocks used in a Memory Pool.
 | |
| uint32_t osMemoryPoolGetCount (osMemoryPoolId_t mp_id) {
 | |
|   uint32_t count;
 | |
| 
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     count = svcRtxMemoryPoolGetCount(mp_id);
 | |
|   } else {
 | |
|     count =  __svcMemoryPoolGetCount(mp_id);
 | |
|   }
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| /// Get number of memory blocks available in a Memory Pool.
 | |
| uint32_t osMemoryPoolGetSpace (osMemoryPoolId_t mp_id) {
 | |
|   uint32_t space;
 | |
| 
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     space = svcRtxMemoryPoolGetSpace(mp_id);
 | |
|   } else {
 | |
|     space =  __svcMemoryPoolGetSpace(mp_id);
 | |
|   }
 | |
|   return space;
 | |
| }
 | |
| 
 | |
| /// Delete a Memory Pool object.
 | |
| osStatus_t osMemoryPoolDelete (osMemoryPoolId_t mp_id) {
 | |
|   osStatus_t status;
 | |
| 
 | |
|   EvrRtxMemoryPoolDelete(mp_id);
 | |
|   if (IsIrqMode() || IsIrqMasked()) {
 | |
|     EvrRtxMemoryPoolError(mp_id, (int32_t)osErrorISR);
 | |
|     status = osErrorISR;
 | |
|   } else {
 | |
|     status = __svcMemoryPoolDelete(mp_id);
 | |
|   }
 | |
|   return status;
 | |
| }
 | 
