kopia lustrzana https://github.com/OpenRTX/OpenRTX
392 wiersze
16 KiB
C
392 wiersze
16 KiB
C
![]() |
/*
|
||
|
*********************************************************************************************************
|
||
|
* uC/OS-III
|
||
|
* The Real-Time Kernel
|
||
|
*
|
||
|
* Copyright 2009-2020 Silicon Laboratories Inc. www.silabs.com
|
||
|
*
|
||
|
* SPDX-License-Identifier: APACHE-2.0
|
||
|
*
|
||
|
* This software is subject to an open source license and is distributed by
|
||
|
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
|
||
|
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
|
||
|
*
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
*********************************************************************************************************
|
||
|
* MEMORY PARTITION MANAGEMENT
|
||
|
*
|
||
|
* File : os_mem.c
|
||
|
* Version : V3.08.00
|
||
|
*********************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
#define MICRIUM_SOURCE
|
||
|
#include "os.h"
|
||
|
|
||
|
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||
|
const CPU_CHAR *os_mem__c = "$Id: $";
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if (OS_CFG_MEM_EN > 0u)
|
||
|
/*
|
||
|
************************************************************************************************************************
|
||
|
* CREATE A MEMORY PARTITION
|
||
|
*
|
||
|
* Description : Create a fixed-sized memory partition that will be managed by uC/OS-III.
|
||
|
*
|
||
|
* Arguments : p_mem is a pointer to a memory partition control block which is allocated in user memory space.
|
||
|
*
|
||
|
* p_name is a pointer to an ASCII string to provide a name to the memory partition.
|
||
|
*
|
||
|
* p_addr is the starting address of the memory partition
|
||
|
*
|
||
|
* n_blks is the number of memory blocks to create from the partition.
|
||
|
*
|
||
|
* blk_size is the size (in bytes) of each block in the memory partition.
|
||
|
*
|
||
|
* p_err is a pointer to a variable containing an error message which will be set by this function to
|
||
|
* either:
|
||
|
*
|
||
|
* OS_ERR_NONE If the memory partition has been created correctly
|
||
|
* OS_ERR_ILLEGAL_CREATE_RUN_TIME If you are trying to create the memory partition after you
|
||
|
* called OSSafetyCriticalStart()
|
||
|
* OS_ERR_MEM_CREATE_ISR If you called this function from an ISR
|
||
|
* OS_ERR_MEM_INVALID_BLKS User specified an invalid number of blocks (must be >= 2)
|
||
|
* OS_ERR_MEM_INVALID_P_ADDR If you are specifying an invalid address for the memory
|
||
|
* storage of the partition or, the block does not align on a
|
||
|
* pointer boundary
|
||
|
* OS_ERR_MEM_INVALID_SIZE User specified an invalid block size
|
||
|
* - must be greater than the size of a pointer
|
||
|
* - must be able to hold an integral number of pointers
|
||
|
* OS_ERR_OBJ_CREATED If the memory partition was already created
|
||
|
* Returns : none
|
||
|
*
|
||
|
* Note(s) : none
|
||
|
************************************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
void OSMemCreate (OS_MEM *p_mem,
|
||
|
CPU_CHAR *p_name,
|
||
|
void *p_addr,
|
||
|
OS_MEM_QTY n_blks,
|
||
|
OS_MEM_SIZE blk_size,
|
||
|
OS_ERR *p_err)
|
||
|
{
|
||
|
#if (OS_CFG_ARG_CHK_EN > 0u)
|
||
|
CPU_DATA align_msk;
|
||
|
#endif
|
||
|
OS_MEM_QTY i;
|
||
|
OS_MEM_QTY loops;
|
||
|
CPU_INT08U *p_blk;
|
||
|
void **p_link;
|
||
|
CPU_SR_ALLOC();
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef OS_SAFETY_CRITICAL
|
||
|
if (p_err == (OS_ERR *)0) {
|
||
|
OS_SAFETY_CRITICAL_EXCEPTION();
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef OS_SAFETY_CRITICAL_IEC61508
|
||
|
if (OSSafetyCriticalStartFlag == OS_TRUE) {
|
||
|
*p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if (OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u)
|
||
|
if (OSIntNestingCtr > 0u) { /* Not allowed to call from an ISR */
|
||
|
*p_err = OS_ERR_MEM_CREATE_ISR;
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if (OS_CFG_ARG_CHK_EN > 0u)
|
||
|
if (p_addr == (void *)0) { /* Must pass a valid address for the memory part. */
|
||
|
*p_err = OS_ERR_MEM_INVALID_P_ADDR;
|
||
|
return;
|
||
|
}
|
||
|
if (n_blks < 2u) { /* Must have at least 2 blocks per partition */
|
||
|
*p_err = OS_ERR_MEM_INVALID_BLKS;
|
||
|
return;
|
||
|
}
|
||
|
if (blk_size < sizeof(void *)) { /* Must contain space for at least a pointer */
|
||
|
*p_err = OS_ERR_MEM_INVALID_SIZE;
|
||
|
return;
|
||
|
}
|
||
|
align_msk = sizeof(void *) - 1u;
|
||
|
if (align_msk > 0u) {
|
||
|
if (((CPU_ADDR)p_addr & align_msk) != 0u){ /* Must be pointer size aligned */
|
||
|
*p_err = OS_ERR_MEM_INVALID_P_ADDR;
|
||
|
return;
|
||
|
}
|
||
|
if ((blk_size & align_msk) != 0u) { /* Block size must be a multiple address size */
|
||
|
*p_err = OS_ERR_MEM_INVALID_SIZE;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
p_link = (void **)p_addr; /* Create linked list of free memory blocks */
|
||
|
p_blk = (CPU_INT08U *)p_addr;
|
||
|
loops = n_blks - 1u;
|
||
|
for (i = 0u; i < loops; i++) {
|
||
|
p_blk += blk_size;
|
||
|
*p_link = (void *)p_blk; /* Save pointer to NEXT block in CURRENT block */
|
||
|
p_link = (void **)(void *)p_blk; /* Position to NEXT block */
|
||
|
}
|
||
|
*p_link = (void *)0; /* Last memory block points to NULL */
|
||
|
|
||
|
CPU_CRITICAL_ENTER();
|
||
|
#if (OS_OBJ_TYPE_REQ > 0u)
|
||
|
if (p_mem->Type == OS_OBJ_TYPE_MEM) {
|
||
|
CPU_CRITICAL_EXIT();
|
||
|
*p_err = OS_ERR_OBJ_CREATED;
|
||
|
return;
|
||
|
}
|
||
|
p_mem->Type = OS_OBJ_TYPE_MEM; /* Set the type of object */
|
||
|
#endif
|
||
|
#if (OS_CFG_DBG_EN > 0u)
|
||
|
p_mem->NamePtr = p_name; /* Save name of memory partition */
|
||
|
#else
|
||
|
(void)p_name;
|
||
|
#endif
|
||
|
p_mem->AddrPtr = p_addr; /* Store start address of memory partition */
|
||
|
p_mem->FreeListPtr = p_addr; /* Initialize pointer to pool of free blocks */
|
||
|
p_mem->NbrFree = n_blks; /* Store number of free blocks in MCB */
|
||
|
p_mem->NbrMax = n_blks;
|
||
|
p_mem->BlkSize = blk_size; /* Store block size of each memory blocks */
|
||
|
|
||
|
#if (OS_CFG_DBG_EN > 0u)
|
||
|
OS_MemDbgListAdd(p_mem);
|
||
|
OSMemQty++;
|
||
|
#endif
|
||
|
|
||
|
OS_TRACE_MEM_CREATE(p_mem, p_name);
|
||
|
CPU_CRITICAL_EXIT();
|
||
|
*p_err = OS_ERR_NONE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
************************************************************************************************************************
|
||
|
* GET A MEMORY BLOCK
|
||
|
*
|
||
|
* Description : Get a memory block from a partition.
|
||
|
*
|
||
|
* Arguments : p_mem is a pointer to the memory partition control block
|
||
|
*
|
||
|
* p_err is a pointer to a variable containing an error message which will be set by this function to
|
||
|
* either:
|
||
|
*
|
||
|
* OS_ERR_NONE If the memory partition has been created correctly
|
||
|
* OS_ERR_MEM_INVALID_P_MEM If you passed a NULL pointer for 'p_mem'
|
||
|
* OS_ERR_MEM_NO_FREE_BLKS If there are no more free memory blocks to allocate to the caller
|
||
|
* OS_ERR_OBJ_TYPE If 'p_mem' is not pointing at a memory partition
|
||
|
*
|
||
|
* Returns : A pointer to a memory block if no error is detected
|
||
|
* A pointer to NULL if an error is detected
|
||
|
*
|
||
|
* Note(s) : none
|
||
|
************************************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
void *OSMemGet (OS_MEM *p_mem,
|
||
|
OS_ERR *p_err)
|
||
|
{
|
||
|
void *p_blk;
|
||
|
CPU_SR_ALLOC();
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef OS_SAFETY_CRITICAL
|
||
|
if (p_err == (OS_ERR *)0) {
|
||
|
OS_SAFETY_CRITICAL_EXCEPTION();
|
||
|
return ((void *)0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
OS_TRACE_MEM_GET_ENTER(p_mem);
|
||
|
|
||
|
#if (OS_CFG_ARG_CHK_EN > 0u)
|
||
|
if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
|
||
|
OS_TRACE_MEM_GET_FAILED(p_mem);
|
||
|
OS_TRACE_MEM_GET_EXIT(OS_ERR_MEM_INVALID_P_MEM);
|
||
|
*p_err = OS_ERR_MEM_INVALID_P_MEM;
|
||
|
return ((void *)0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
|
||
|
if (p_mem->Type != OS_OBJ_TYPE_MEM) { /* Make sure the memory block was created */
|
||
|
OS_TRACE_MEM_GET_EXIT(OS_ERR_OBJ_TYPE);
|
||
|
*p_err = OS_ERR_OBJ_TYPE;
|
||
|
return ((void *)0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
CPU_CRITICAL_ENTER();
|
||
|
if (p_mem->NbrFree == 0u) { /* See if there are any free memory blocks */
|
||
|
CPU_CRITICAL_EXIT();
|
||
|
OS_TRACE_MEM_GET_FAILED(p_mem);
|
||
|
OS_TRACE_MEM_GET_EXIT(OS_ERR_MEM_NO_FREE_BLKS);
|
||
|
*p_err = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */
|
||
|
return ((void *)0); /* Return NULL pointer to caller */
|
||
|
}
|
||
|
p_blk = p_mem->FreeListPtr; /* Yes, point to next free memory block */
|
||
|
p_mem->FreeListPtr = *(void **)p_blk; /* Adjust pointer to new free list */
|
||
|
p_mem->NbrFree--; /* One less memory block in this partition */
|
||
|
CPU_CRITICAL_EXIT();
|
||
|
OS_TRACE_MEM_GET(p_mem);
|
||
|
OS_TRACE_MEM_GET_EXIT(OS_ERR_NONE);
|
||
|
*p_err = OS_ERR_NONE; /* No error */
|
||
|
return (p_blk); /* Return memory block to caller */
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
************************************************************************************************************************
|
||
|
* RELEASE A MEMORY BLOCK
|
||
|
*
|
||
|
* Description : Returns a memory block to a partition.
|
||
|
*
|
||
|
* Arguments : p_mem is a pointer to the memory partition control block
|
||
|
*
|
||
|
* p_blk is a pointer to the memory block being released.
|
||
|
*
|
||
|
* p_err is a pointer to a variable that will contain an error code returned by this function.
|
||
|
*
|
||
|
* OS_ERR_NONE If the memory block was inserted into the partition
|
||
|
* OS_ERR_MEM_FULL If you are returning a memory block to an already FULL memory
|
||
|
* partition (You freed more blocks than you allocated!)
|
||
|
* OS_ERR_MEM_INVALID_P_BLK If you passed a NULL pointer for the block to release.
|
||
|
* OS_ERR_MEM_INVALID_P_MEM If you passed a NULL pointer for 'p_mem'
|
||
|
* OS_ERR_OBJ_TYPE If 'p_mem' is not pointing at a memory partition
|
||
|
*
|
||
|
* Returns : none
|
||
|
*
|
||
|
* Note(s) : none
|
||
|
************************************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
void OSMemPut (OS_MEM *p_mem,
|
||
|
void *p_blk,
|
||
|
OS_ERR *p_err)
|
||
|
{
|
||
|
CPU_SR_ALLOC();
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef OS_SAFETY_CRITICAL
|
||
|
if (p_err == (OS_ERR *)0) {
|
||
|
OS_SAFETY_CRITICAL_EXCEPTION();
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
OS_TRACE_MEM_PUT_ENTER(p_mem, p_blk);
|
||
|
|
||
|
#if (OS_CFG_ARG_CHK_EN > 0u)
|
||
|
if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
|
||
|
OS_TRACE_MEM_PUT_FAILED(p_mem);
|
||
|
OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_INVALID_P_MEM);
|
||
|
*p_err = OS_ERR_MEM_INVALID_P_MEM;
|
||
|
return;
|
||
|
}
|
||
|
if (p_blk == (void *)0) { /* Must release a valid block */
|
||
|
OS_TRACE_MEM_PUT_FAILED(p_mem);
|
||
|
OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_INVALID_P_BLK);
|
||
|
*p_err = OS_ERR_MEM_INVALID_P_BLK;
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if (OS_CFG_OBJ_TYPE_CHK_EN > 0u)
|
||
|
if (p_mem->Type != OS_OBJ_TYPE_MEM) { /* Make sure the memory block was created */
|
||
|
OS_TRACE_MEM_PUT_EXIT(OS_ERR_OBJ_TYPE);
|
||
|
*p_err = OS_ERR_OBJ_TYPE;
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
CPU_CRITICAL_ENTER();
|
||
|
if (p_mem->NbrFree >= p_mem->NbrMax) { /* Make sure all blocks not already returned */
|
||
|
CPU_CRITICAL_EXIT();
|
||
|
OS_TRACE_MEM_PUT_FAILED(p_mem);
|
||
|
OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_FULL);
|
||
|
*p_err = OS_ERR_MEM_FULL;
|
||
|
return;
|
||
|
}
|
||
|
*(void **)p_blk = p_mem->FreeListPtr; /* Insert released block into free block list */
|
||
|
p_mem->FreeListPtr = p_blk;
|
||
|
p_mem->NbrFree++; /* One more memory block in this partition */
|
||
|
CPU_CRITICAL_EXIT();
|
||
|
OS_TRACE_MEM_PUT(p_mem);
|
||
|
OS_TRACE_MEM_PUT_EXIT(OS_ERR_NONE);
|
||
|
*p_err = OS_ERR_NONE; /* Notify caller that memory block was released */
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
************************************************************************************************************************
|
||
|
* ADD MEMORY PARTITION TO DEBUG LIST
|
||
|
*
|
||
|
* Description : This function is called by OSMemCreate() to add the memory partition to the debug table.
|
||
|
*
|
||
|
* Arguments : p_mem Is a pointer to the memory partition
|
||
|
*
|
||
|
* Returns : none
|
||
|
*
|
||
|
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||
|
************************************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
#if (OS_CFG_DBG_EN > 0u)
|
||
|
void OS_MemDbgListAdd (OS_MEM *p_mem)
|
||
|
{
|
||
|
p_mem->DbgPrevPtr = (OS_MEM *)0;
|
||
|
if (OSMemDbgListPtr == (OS_MEM *)0) {
|
||
|
p_mem->DbgNextPtr = (OS_MEM *)0;
|
||
|
} else {
|
||
|
p_mem->DbgNextPtr = OSMemDbgListPtr;
|
||
|
OSMemDbgListPtr->DbgPrevPtr = p_mem;
|
||
|
}
|
||
|
OSMemDbgListPtr = p_mem;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*
|
||
|
************************************************************************************************************************
|
||
|
* INITIALIZE MEMORY PARTITION MANAGER
|
||
|
*
|
||
|
* Description : This function is called by uC/OS-III to initialize the memory partition manager. Your
|
||
|
* application MUST NOT call this function.
|
||
|
*
|
||
|
* Arguments : none
|
||
|
*
|
||
|
* Returns : none
|
||
|
*
|
||
|
* Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
|
||
|
************************************************************************************************************************
|
||
|
*/
|
||
|
|
||
|
void OS_MemInit (OS_ERR *p_err)
|
||
|
{
|
||
|
#if (OS_CFG_DBG_EN > 0u)
|
||
|
OSMemDbgListPtr = (OS_MEM *)0;
|
||
|
OSMemQty = 0u;
|
||
|
#endif
|
||
|
*p_err = OS_ERR_NONE;
|
||
|
}
|
||
|
#endif
|