diff options
Diffstat (limited to 'atmel-samd/asf/common/utils/membag/membag.c')
| -rw-r--r-- | atmel-samd/asf/common/utils/membag/membag.c | 325 |
1 files changed, 0 insertions, 325 deletions
diff --git a/atmel-samd/asf/common/utils/membag/membag.c b/atmel-samd/asf/common/utils/membag/membag.c deleted file mode 100644 index c6a50c059..000000000 --- a/atmel-samd/asf/common/utils/membag/membag.c +++ /dev/null @@ -1,325 +0,0 @@ -/** - * \file - * - * \brief Memory bag allocator - * - * Copyright (C) 2012-2015 Atmel Corporation. All rights reserved. - * - * \asf_license_start - * - * \page License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of Atmel may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * 4. This software may only be redistributed and used in connection with an - * Atmel microcontroller product. - * - * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE - * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * \asf_license_stop - * - */ -/* - * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> - */ - -#include <compiler.h> -#include <membag.h> -#include "conf_membag.h" - -/** \internal - * - * Retrieves the number of elements in a statically declared array. - */ -#define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) - -/** - * Static address space which is split up into usable chunks by membag. - * For configuration details, see \ref membag_list. - */ -static uint8_t membag_pool[CONF_MEMBAG_POOL_SIZE]; - -/** - * Internal structure used by membag to keep track of memory, - * with maximum 32 blocks per membag. - */ -struct membag { - /*! Number of bytes per block in this bag. */ - size_t block_size; - /*! Total number of blocks. */ - size_t num_blocks; - /*! Pointer to start of this bag. */ - uintptr_t start; - /*! Pointer to end of this bag. */ - uintptr_t end; - /*! 32-bit integer used to keep track of allocations. */ - uint32_t allocated; - /*! Counter for number of free blocks. */ - uint8_t blocks_free; -}; - -/** - * Array of available membags, provided by the user in the applications - * conf_membag.h header file. Example: - * - * \code - #define CONF_MEMBAG_ARRAY \ - MEMBAG(32, 4), \ - MEMBAG(16, 2), - - #define CONF_MEMBAG_POOL_SIZE \ - MEMBAG_SIZE(32, 4) + \ - MEMBAG_SIZE(16, 2) -\endcode - * - */ -static struct membag membag_list[] = { - CONF_MEMBAG_ARRAY -}; - -/** - * \brief Initialize the membag system. - * - * This function sets up the membags, allocates memory from the memory pool, and - * initializes them. Any existing allocations are destroyed and all memory pools - * reset to their initial states. - */ -void membag_init(void) -{ - uint8_t i; - uintptr_t poolptr; - - poolptr = (uintptr_t)membag_pool; - - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - Assert(membag_list[i].block_size > 0); - Assert(membag_list[i].num_blocks > 0); - Assert(membag_list[i].num_blocks <= 32); - - membag_list[i].start = poolptr; - poolptr += (membag_list[i].block_size * - membag_list[i].num_blocks); - membag_list[i].end = poolptr; - membag_list[i].blocks_free = membag_list[i].num_blocks; - - /* Mark all blocks as free. */ - membag_list[i].allocated = 0; - } -} - -/** - * \brief Determine the total remaining free memory from all membags. - * - * \return Sum of all free memory, in bytes. - */ -size_t membag_get_total_free(void) -{ - uint8_t i; - size_t total_free = 0; - - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - total_free += membag_list[i].blocks_free * - membag_list[i].block_size; - } - - return total_free; -} - -/** - * \brief Determine the total memory from all membags. - * - * \return Sum of all blocks in all bags, in bytes. - */ -size_t membag_get_total(void) -{ - uint8_t i; - size_t total = 0; - - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - total += membag_list[i].num_blocks * membag_list[i].block_size; - } - - return total; -} - -/** - * \brief Determine the smallest available block size. - * - * Calculates the smallest block which can be allocated by the Membag allocator - * if requested. Allocations larger than this amount are not guaranteed to - * complete successfully. - * - * \return Size of the smallest available block, in bytes. - */ -size_t membag_get_smallest_free_block_size(void) -{ - uint8_t i; - struct membag *smallest_bag = NULL; - - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - if (membag_list[i].blocks_free == 0) { - continue; - } - - if (!smallest_bag || - (smallest_bag->block_size > membag_list[i].block_size)) { - smallest_bag = &membag_list[i]; - } - } - - if (smallest_bag) { - return smallest_bag->block_size; - } - - return 0; -} - -/** - * \brief Determine the largest available block size. - * - * Calculates the largest block which can be allocated by the Membag allocator - * if requested. Allocations larger than this amount are guaranteed to fail. - * - * \return Size of the largest available block, in bytes. - */ -size_t membag_get_largest_free_block_size(void) -{ - uint8_t i; - struct membag *largest_bag = NULL; - - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - if (membag_list[i].blocks_free == 0) { - continue; - } - - if (!largest_bag || - (largest_bag->block_size < membag_list[i].block_size)) { - largest_bag = &membag_list[i]; - } - } - - if (largest_bag) { - return largest_bag->block_size; - } - - return 0; -} - -/** - * \brief Allocate a memory block via a block from the Membag pool - * - * Allocates memory to the user from one of the available Membag pools. Each - * Membag pool is examined in sequence, and the first free block of sufficient - * size (if any) is chosen for the allocation. Allocated blocks persist until - * either the Membag module is re-initialized, or an allocation block is freed - * via \ref membag_free(). - * - * \note The execution cycle time for this function is not deterministic; each - * allocation request may take a variable amount of cycles to complete. - * - * \param size Size of memory block requested, in bytes - * - * \return Pointer to the start of an allocated block if one was found in the - * Membag pool, NULL if no suitable block was found. - */ -void *membag_alloc(const size_t size) -{ - uint8_t i; - struct membag *smallest_bag = NULL; - uintptr_t p; - - /* Find the smallest available block size big enough for the requested - * memory chunk size. */ - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - if (membag_list[i].blocks_free == 0) { - continue; - } - - if (membag_list[i].block_size >= size) { - if (!smallest_bag || - (smallest_bag->block_size > membag_list[i].block_size)) { - smallest_bag = &membag_list[i]; - } - } - } - - /* We return the first available block in the bag that has one, and if - * there is none, we return NULL. - */ - if (smallest_bag) { - /* We know that there is a free block within the membag's - * memory, and we simply return the first one available. - */ - p = smallest_bag->start; - - for (i = 0; i < smallest_bag->num_blocks; i++) { - /* Check the allocation byte to see whether the block is - * in use. */ - if (!(smallest_bag->allocated & ((uint32_t)1 << i))) { - /* It is free, set it to used. */ - smallest_bag->allocated |= ((uint32_t)1 << i); - smallest_bag->blocks_free--; - - return (void *)(p); - } - - p += smallest_bag->block_size; - } - } - - /* There is no available memory. Return NULL. */ - return NULL; -} - -/** - * \brief Free a previously allocated memory block from the Membag pool - * - * This function frees memory which has been allocated previously via a - * successful call to \ref membag_alloc(). Once deallocated, the given pointer - * is no longer valid and should not be used in the user application unless - * re-allocated. - * - * \note The execution cycle time for this function is not deterministic; each - * allocation request may take a variable amount of cycles to complete. - * - * \param ptr Pointer to an allocated memory block to free - */ -void membag_free(const void *ptr) -{ - uint8_t i; - uintptr_t p = (uintptr_t)ptr; - uint8_t block_index; - - for (i = 0; i < ARRAY_LEN(membag_list); i++) { - if (p >= membag_list[i].start && p < membag_list[i].end) { - block_index = (p - membag_list[i].start) / membag_list[i].block_size; - - /* Mark the memory as free. */ - membag_list[i].allocated &= ~((uint32_t)1 << block_index); - membag_list[i].blocks_free++; - - return; - } - } -} |
