A library implementing IEEE 802.15.4 PHY functionality for the MCR20A transceiver. The PHY sublayer provides two services: the PHY data service and the PHY management service interfacing to the PHY sublayer management entity (PLME) service access point (SAP) (known as PLME-SAP). The PHY data service enables the transmission and reception of PHY protocol data units (PSDUs) over the media (radio).

Fork of fsl_phy_mcr20a by Freescale

The Freescale PHY Layer deals with the physical burst which is to be sent and/or received. It performs modulation and demodulation, transmitter and receiver switching, fragmentation, scrambling, interleaving, and error correction coding. The communication to the upper protocol layers is carried out through the Layer 1 Interface.

The PHY Layer is capable of executing the following sequences:

  • I (Idle)
  • R (Receive Sequence conditionally followed by a TxAck)
  • T (Transmit Sequence)
  • C (Standalone CCA)
  • CCCA (Continuous CCA)
  • TR (Transmit/Receive Sequence - transmit unconditionally followed by either an R or RxAck)

In addition to these sequences the PHY Layer also integrates a packet processor which determines whether the packet is MAC-compliant, and if it is, whether it is addressed to the end device. Another feature of the packet processor is Source Address Matching which can be viewed as an extension of packet filtering; however its function is very specific to its intended application (data-polling and indirect queue management by a PAN Coordinator).

Documentation

MCR20A PHY Reference Manual

Committer:
andreikovacs
Date:
Tue Aug 18 12:41:42 2015 +0000
Revision:
0:764779eedf2d
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andreikovacs 0:764779eedf2d 1 /*!
andreikovacs 0:764779eedf2d 2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
andreikovacs 0:764779eedf2d 3 * All rights reserved.
andreikovacs 0:764779eedf2d 4 *
andreikovacs 0:764779eedf2d 5 * \file MemManager.c
andreikovacs 0:764779eedf2d 6 * This is the source file for the Memory Manager.
andreikovacs 0:764779eedf2d 7 *
andreikovacs 0:764779eedf2d 8 * Redistribution and use in source and binary forms, with or without modification,
andreikovacs 0:764779eedf2d 9 * are permitted provided that the following conditions are met:
andreikovacs 0:764779eedf2d 10 *
andreikovacs 0:764779eedf2d 11 * o Redistributions of source code must retain the above copyright notice, this list
andreikovacs 0:764779eedf2d 12 * of conditions and the following disclaimer.
andreikovacs 0:764779eedf2d 13 *
andreikovacs 0:764779eedf2d 14 * o Redistributions in binary form must reproduce the above copyright notice, this
andreikovacs 0:764779eedf2d 15 * list of conditions and the following disclaimer in the documentation and/or
andreikovacs 0:764779eedf2d 16 * other materials provided with the distribution.
andreikovacs 0:764779eedf2d 17 *
andreikovacs 0:764779eedf2d 18 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
andreikovacs 0:764779eedf2d 19 * contributors may be used to endorse or promote products derived from this
andreikovacs 0:764779eedf2d 20 * software without specific prior written permission.
andreikovacs 0:764779eedf2d 21 *
andreikovacs 0:764779eedf2d 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
andreikovacs 0:764779eedf2d 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
andreikovacs 0:764779eedf2d 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
andreikovacs 0:764779eedf2d 25 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
andreikovacs 0:764779eedf2d 26 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
andreikovacs 0:764779eedf2d 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
andreikovacs 0:764779eedf2d 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
andreikovacs 0:764779eedf2d 29 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
andreikovacs 0:764779eedf2d 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
andreikovacs 0:764779eedf2d 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
andreikovacs 0:764779eedf2d 32 */
andreikovacs 0:764779eedf2d 33
andreikovacs 0:764779eedf2d 34
andreikovacs 0:764779eedf2d 35 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 36 *************************************************************************************
andreikovacs 0:764779eedf2d 37 * Include
andreikovacs 0:764779eedf2d 38 *************************************************************************************
andreikovacs 0:764779eedf2d 39 ********************************************************************************** */
andreikovacs 0:764779eedf2d 40 #include "EmbeddedTypes.h"
andreikovacs 0:764779eedf2d 41 #include "mbedAbstraction.h"
andreikovacs 0:764779eedf2d 42 #include "fsl_os_abstraction.h"
andreikovacs 0:764779eedf2d 43 #ifdef MEM_DEBUG
andreikovacs 0:764779eedf2d 44 #include "Panic.h"
andreikovacs 0:764779eedf2d 45 #endif
andreikovacs 0:764779eedf2d 46 #include "MemManager.h"
andreikovacs 0:764779eedf2d 47
andreikovacs 0:764779eedf2d 48
andreikovacs 0:764779eedf2d 49 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 50 *************************************************************************************
andreikovacs 0:764779eedf2d 51 * Private memory declarations
andreikovacs 0:764779eedf2d 52 *************************************************************************************
andreikovacs 0:764779eedf2d 53 ********************************************************************************** */
andreikovacs 0:764779eedf2d 54
andreikovacs 0:764779eedf2d 55 #define _block_size_ {
andreikovacs 0:764779eedf2d 56 #define _number_of_blocks_ ,
andreikovacs 0:764779eedf2d 57 #define _eol_ },
andreikovacs 0:764779eedf2d 58
andreikovacs 0:764779eedf2d 59 poolInfo_t poolInfo[] =
andreikovacs 0:764779eedf2d 60 {
andreikovacs 0:764779eedf2d 61 PoolsDetails_c
andreikovacs 0:764779eedf2d 62 {0, 0} /*termination tag*/
andreikovacs 0:764779eedf2d 63 };
andreikovacs 0:764779eedf2d 64
andreikovacs 0:764779eedf2d 65 #undef _block_size_
andreikovacs 0:764779eedf2d 66 #undef _number_of_blocks_
andreikovacs 0:764779eedf2d 67 #undef _eol_
andreikovacs 0:764779eedf2d 68
andreikovacs 0:764779eedf2d 69 #define _block_size_ (sizeof(listHeader_t)+
andreikovacs 0:764779eedf2d 70 #define _number_of_blocks_ ) *
andreikovacs 0:764779eedf2d 71 #define _eol_ +
andreikovacs 0:764779eedf2d 72
andreikovacs 0:764779eedf2d 73 #define heapSize_c (PoolsDetails_c 0)
andreikovacs 0:764779eedf2d 74
andreikovacs 0:764779eedf2d 75 // Heap
andreikovacs 0:764779eedf2d 76 uint8_t memHeap[heapSize_c];
andreikovacs 0:764779eedf2d 77 const uint32_t heapSize = heapSize_c;
andreikovacs 0:764779eedf2d 78
andreikovacs 0:764779eedf2d 79 #undef _block_size_
andreikovacs 0:764779eedf2d 80 #undef _number_of_blocks_
andreikovacs 0:764779eedf2d 81 #undef _eol_
andreikovacs 0:764779eedf2d 82
andreikovacs 0:764779eedf2d 83 #define _block_size_ 0 *
andreikovacs 0:764779eedf2d 84 #define _number_of_blocks_ + 0 *
andreikovacs 0:764779eedf2d 85 #define _eol_ + 1 +
andreikovacs 0:764779eedf2d 86
andreikovacs 0:764779eedf2d 87 #define poolCount (PoolsDetails_c 0)
andreikovacs 0:764779eedf2d 88
andreikovacs 0:764779eedf2d 89 // Memory pool info and anchors.
andreikovacs 0:764779eedf2d 90 pools_t memPools[poolCount];
andreikovacs 0:764779eedf2d 91
andreikovacs 0:764779eedf2d 92 #undef _block_size_
andreikovacs 0:764779eedf2d 93 #undef _number_of_blocks_
andreikovacs 0:764779eedf2d 94 #undef _eol_
andreikovacs 0:764779eedf2d 95
andreikovacs 0:764779eedf2d 96 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 97
andreikovacs 0:764779eedf2d 98 #define _block_size_ 0*
andreikovacs 0:764779eedf2d 99 #define _number_of_blocks_ +
andreikovacs 0:764779eedf2d 100 #define _eol_ +
andreikovacs 0:764779eedf2d 101
andreikovacs 0:764779eedf2d 102 #define mTotalNoOfMsgs_d (PoolsDetails_c 0)
andreikovacs 0:764779eedf2d 103 static const uint16_t mTotalNoOfMsgs_c = mTotalNoOfMsgs_d;
andreikovacs 0:764779eedf2d 104 blockTracking_t memTrack[mTotalNoOfMsgs_d];
andreikovacs 0:764779eedf2d 105
andreikovacs 0:764779eedf2d 106 #undef _block_size_
andreikovacs 0:764779eedf2d 107 #undef _number_of_blocks_
andreikovacs 0:764779eedf2d 108 #undef _eol_
andreikovacs 0:764779eedf2d 109
andreikovacs 0:764779eedf2d 110 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 111
andreikovacs 0:764779eedf2d 112 // Free messages counter. Not used by module.
andreikovacs 0:764779eedf2d 113 uint16_t gFreeMessagesCount;
andreikovacs 0:764779eedf2d 114
andreikovacs 0:764779eedf2d 115 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 116 *************************************************************************************
andreikovacs 0:764779eedf2d 117 * Public functions
andreikovacs 0:764779eedf2d 118 *************************************************************************************
andreikovacs 0:764779eedf2d 119 ********************************************************************************** */
andreikovacs 0:764779eedf2d 120
andreikovacs 0:764779eedf2d 121 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 122 * \brief This function initializes the message module private variables.
andreikovacs 0:764779eedf2d 123 * Must be called at boot time, or if device is reset.
andreikovacs 0:764779eedf2d 124 *
andreikovacs 0:764779eedf2d 125 * \param[in] none
andreikovacs 0:764779eedf2d 126 *
andreikovacs 0:764779eedf2d 127 * \return MEM_SUCCESS_c if initialization is successful. (It's always successful).
andreikovacs 0:764779eedf2d 128 *
andreikovacs 0:764779eedf2d 129 ********************************************************************************** */
andreikovacs 0:764779eedf2d 130 memStatus_t MEM_Init()
andreikovacs 0:764779eedf2d 131 {
andreikovacs 0:764779eedf2d 132 poolInfo_t *pPoolInfo = poolInfo; // IN: Memory layout information
andreikovacs 0:764779eedf2d 133 pools_t *pPools = memPools;// OUT: Will be initialized with requested memory pools.
andreikovacs 0:764779eedf2d 134 uint8_t *pHeap = memHeap;// IN: Memory heap.
andreikovacs 0:764779eedf2d 135 uint8_t poolN;
andreikovacs 0:764779eedf2d 136 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 137 uint16_t memTrackIndex = 0;
andreikovacs 0:764779eedf2d 138 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 139
andreikovacs 0:764779eedf2d 140 gFreeMessagesCount = 0;
andreikovacs 0:764779eedf2d 141
andreikovacs 0:764779eedf2d 142 for(;;)
andreikovacs 0:764779eedf2d 143 {
andreikovacs 0:764779eedf2d 144 poolN = pPoolInfo->poolSize;
andreikovacs 0:764779eedf2d 145 ListInit((listHandle_t)&pPools->anchor, poolN);
andreikovacs 0:764779eedf2d 146 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 147 pPools->poolStatistics.numBlocks = 0;
andreikovacs 0:764779eedf2d 148 pPools->poolStatistics.allocatedBlocks = 0;
andreikovacs 0:764779eedf2d 149 pPools->poolStatistics.allocatedBlocksPeak = 0;
andreikovacs 0:764779eedf2d 150 pPools->poolStatistics.allocationFailures = 0;
andreikovacs 0:764779eedf2d 151 pPools->poolStatistics.freeFailures = 0;
andreikovacs 0:764779eedf2d 152 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 153 pPools->poolStatistics.poolFragmentWaste = 0;
andreikovacs 0:764779eedf2d 154 pPools->poolStatistics.poolFragmentWastePeak = 0;
andreikovacs 0:764779eedf2d 155 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 156 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 157
andreikovacs 0:764779eedf2d 158 while(poolN)
andreikovacs 0:764779eedf2d 159 {
andreikovacs 0:764779eedf2d 160 // Add block to list of free memory.
andreikovacs 0:764779eedf2d 161 ListAddTail((listHandle_t)&pPools->anchor, (listElementHandle_t)&((listHeader_t *)pHeap)->link);
andreikovacs 0:764779eedf2d 162 ((listHeader_t *)pHeap)->pParentPool = pPools;
andreikovacs 0:764779eedf2d 163 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 164 pPools->poolStatistics.numBlocks++;
andreikovacs 0:764779eedf2d 165 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 166
andreikovacs 0:764779eedf2d 167 gFreeMessagesCount++;
andreikovacs 0:764779eedf2d 168 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 169 memTrack[memTrackIndex].blockAddr = (void *)(pHeap + sizeof(listHeader_t));
andreikovacs 0:764779eedf2d 170 memTrack[memTrackIndex].blockSize = pPoolInfo->blockSize;
andreikovacs 0:764779eedf2d 171 memTrack[memTrackIndex].fragmentWaste = 0;
andreikovacs 0:764779eedf2d 172 memTrack[memTrackIndex].allocAddr = NULL;
andreikovacs 0:764779eedf2d 173 memTrack[memTrackIndex].allocCounter = 0;
andreikovacs 0:764779eedf2d 174 memTrack[memTrackIndex].allocStatus = MEM_TRACKING_FREE_c;
andreikovacs 0:764779eedf2d 175 memTrack[memTrackIndex].freeAddr = NULL;
andreikovacs 0:764779eedf2d 176 memTrack[memTrackIndex].freeCounter = 0;
andreikovacs 0:764779eedf2d 177 memTrackIndex++;
andreikovacs 0:764779eedf2d 178 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 179
andreikovacs 0:764779eedf2d 180 // Add block size (without list header)
andreikovacs 0:764779eedf2d 181 pHeap += pPoolInfo->blockSize + sizeof(listHeader_t);
andreikovacs 0:764779eedf2d 182 poolN--;
andreikovacs 0:764779eedf2d 183 }
andreikovacs 0:764779eedf2d 184
andreikovacs 0:764779eedf2d 185 pPools->blockSize = pPoolInfo->blockSize;
andreikovacs 0:764779eedf2d 186 pPools->nextBlockSize = (pPoolInfo+1)->blockSize;
andreikovacs 0:764779eedf2d 187 if(pPools->nextBlockSize == 0)
andreikovacs 0:764779eedf2d 188 {
andreikovacs 0:764779eedf2d 189 break;
andreikovacs 0:764779eedf2d 190 }
andreikovacs 0:764779eedf2d 191
andreikovacs 0:764779eedf2d 192 pPools++;
andreikovacs 0:764779eedf2d 193 pPoolInfo++;
andreikovacs 0:764779eedf2d 194 }
andreikovacs 0:764779eedf2d 195 return MEM_SUCCESS_c;
andreikovacs 0:764779eedf2d 196 }
andreikovacs 0:764779eedf2d 197
andreikovacs 0:764779eedf2d 198 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 199 * \brief This function returns the number of available blocks greater or
andreikovacs 0:764779eedf2d 200 * equal to the given size.
andreikovacs 0:764779eedf2d 201 *
andreikovacs 0:764779eedf2d 202 * \param[in] size - Size of blocks to check for availability.
andreikovacs 0:764779eedf2d 203 *
andreikovacs 0:764779eedf2d 204 * \return Number of available blocks greater or equal to the given size.
andreikovacs 0:764779eedf2d 205 *
andreikovacs 0:764779eedf2d 206 * \pre Memory manager must be previously initialized.
andreikovacs 0:764779eedf2d 207 *
andreikovacs 0:764779eedf2d 208 ********************************************************************************** */
andreikovacs 0:764779eedf2d 209 uint32_t MEM_GetAvailableBlocks
andreikovacs 0:764779eedf2d 210 (
andreikovacs 0:764779eedf2d 211 uint32_t size
andreikovacs 0:764779eedf2d 212 )
andreikovacs 0:764779eedf2d 213 {
andreikovacs 0:764779eedf2d 214 pools_t *pPools = memPools;
andreikovacs 0:764779eedf2d 215 uint32_t pTotalCount = 0;
andreikovacs 0:764779eedf2d 216
andreikovacs 0:764779eedf2d 217 for(;;)
andreikovacs 0:764779eedf2d 218 {
andreikovacs 0:764779eedf2d 219 if(size <= pPools->blockSize)
andreikovacs 0:764779eedf2d 220 {
andreikovacs 0:764779eedf2d 221 pTotalCount += ListGetSize((listHandle_t)&pPools->anchor);
andreikovacs 0:764779eedf2d 222 }
andreikovacs 0:764779eedf2d 223
andreikovacs 0:764779eedf2d 224 if(pPools->nextBlockSize == 0)
andreikovacs 0:764779eedf2d 225 {
andreikovacs 0:764779eedf2d 226 break;
andreikovacs 0:764779eedf2d 227 }
andreikovacs 0:764779eedf2d 228
andreikovacs 0:764779eedf2d 229 pPools++;
andreikovacs 0:764779eedf2d 230 }
andreikovacs 0:764779eedf2d 231
andreikovacs 0:764779eedf2d 232 return pTotalCount;
andreikovacs 0:764779eedf2d 233 }
andreikovacs 0:764779eedf2d 234
andreikovacs 0:764779eedf2d 235 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 236 * \brief Allocate a block from the memory pools. The function uses the
andreikovacs 0:764779eedf2d 237 * numBytes argument to look up a pool with adequate block sizes.
andreikovacs 0:764779eedf2d 238 * \param[in] numBytes - Size of buffer to allocate.
andreikovacs 0:764779eedf2d 239 *
andreikovacs 0:764779eedf2d 240 * \return Pointer to the allocated buffer, NULL if failed.
andreikovacs 0:764779eedf2d 241 *
andreikovacs 0:764779eedf2d 242 * \pre Memory manager must be previously initialized.
andreikovacs 0:764779eedf2d 243 *
andreikovacs 0:764779eedf2d 244 ********************************************************************************** */
andreikovacs 0:764779eedf2d 245 void* MEM_BufferAlloc
andreikovacs 0:764779eedf2d 246 (
andreikovacs 0:764779eedf2d 247 uint32_t numBytes // IN: Minimum number of bytes to allocate
andreikovacs 0:764779eedf2d 248 )
andreikovacs 0:764779eedf2d 249 {
andreikovacs 0:764779eedf2d 250 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 251
andreikovacs 0:764779eedf2d 252 /* Save the Link Register */
andreikovacs 0:764779eedf2d 253 volatile uint32_t savedLR;
andreikovacs 0:764779eedf2d 254 // __asm("str r14, [SP]");
andreikovacs 0:764779eedf2d 255 __asm("push {r2} ");
andreikovacs 0:764779eedf2d 256 __asm("push {LR} ");
andreikovacs 0:764779eedf2d 257 __asm("pop {r2} ");
andreikovacs 0:764779eedf2d 258 __asm("str r2, [SP, #4]");
andreikovacs 0:764779eedf2d 259 __asm("pop {r2}");
andreikovacs 0:764779eedf2d 260
andreikovacs 0:764779eedf2d 261 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 262
andreikovacs 0:764779eedf2d 263 pools_t *pPools = memPools;
andreikovacs 0:764779eedf2d 264 listHeader_t *pBlock;
andreikovacs 0:764779eedf2d 265
andreikovacs 0:764779eedf2d 266 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 267 uint16_t requestedSize = numBytes;
andreikovacs 0:764779eedf2d 268 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 269
andreikovacs 0:764779eedf2d 270 OSA_EnterCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 271
andreikovacs 0:764779eedf2d 272 while(numBytes)
andreikovacs 0:764779eedf2d 273 {
andreikovacs 0:764779eedf2d 274 if(numBytes <= pPools->blockSize)
andreikovacs 0:764779eedf2d 275 {
andreikovacs 0:764779eedf2d 276 pBlock = (listHeader_t *)ListRemoveHead((listHandle_t)&pPools->anchor);
andreikovacs 0:764779eedf2d 277
andreikovacs 0:764779eedf2d 278 if(NULL != pBlock)
andreikovacs 0:764779eedf2d 279 {
andreikovacs 0:764779eedf2d 280 pBlock++;
andreikovacs 0:764779eedf2d 281 gFreeMessagesCount--;
andreikovacs 0:764779eedf2d 282
andreikovacs 0:764779eedf2d 283 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 284 pPools->poolStatistics.allocatedBlocks++;
andreikovacs 0:764779eedf2d 285 if ( pPools->poolStatistics.allocatedBlocks > pPools->poolStatistics.allocatedBlocksPeak )
andreikovacs 0:764779eedf2d 286 {
andreikovacs 0:764779eedf2d 287 pPools->poolStatistics.allocatedBlocksPeak = pPools->poolStatistics.allocatedBlocks;
andreikovacs 0:764779eedf2d 288 }
andreikovacs 0:764779eedf2d 289 MEM_ASSERT(pPools->poolStatistics.allocatedBlocks <= pPools->poolStatistics.numBlocks);
andreikovacs 0:764779eedf2d 290 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 291
andreikovacs 0:764779eedf2d 292 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 293 MEM_Track(pBlock, MEM_TRACKING_ALLOC_c, savedLR, requestedSize);
andreikovacs 0:764779eedf2d 294 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 295 OSA_ExitCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 296 return pBlock;
andreikovacs 0:764779eedf2d 297 }
andreikovacs 0:764779eedf2d 298 else
andreikovacs 0:764779eedf2d 299 {
andreikovacs 0:764779eedf2d 300 if(numBytes > pPools->nextBlockSize) break;
andreikovacs 0:764779eedf2d 301 // No more blocks of that size, try next size.
andreikovacs 0:764779eedf2d 302 numBytes = pPools->nextBlockSize;
andreikovacs 0:764779eedf2d 303 }
andreikovacs 0:764779eedf2d 304 }
andreikovacs 0:764779eedf2d 305 // Try next pool
andreikovacs 0:764779eedf2d 306 if(pPools->nextBlockSize)
andreikovacs 0:764779eedf2d 307 pPools++;
andreikovacs 0:764779eedf2d 308 else
andreikovacs 0:764779eedf2d 309 break;
andreikovacs 0:764779eedf2d 310 }
andreikovacs 0:764779eedf2d 311 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 312 pPools->poolStatistics.allocationFailures++;
andreikovacs 0:764779eedf2d 313 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 314
andreikovacs 0:764779eedf2d 315 #ifdef MEM_DEBUG
andreikovacs 0:764779eedf2d 316 panic( 0, (uint32_t)MEM_BufferAlloc, 0, 0);
andreikovacs 0:764779eedf2d 317 #endif
andreikovacs 0:764779eedf2d 318
andreikovacs 0:764779eedf2d 319 OSA_ExitCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 320 return NULL;
andreikovacs 0:764779eedf2d 321 }
andreikovacs 0:764779eedf2d 322
andreikovacs 0:764779eedf2d 323 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 324 * \brief Deallocate a memory block by putting it in the corresponding pool
andreikovacs 0:764779eedf2d 325 * of free blocks.
andreikovacs 0:764779eedf2d 326 *
andreikovacs 0:764779eedf2d 327 * \param[in] buffer - Pointer to buffer to deallocate.
andreikovacs 0:764779eedf2d 328 *
andreikovacs 0:764779eedf2d 329 * \return MEM_SUCCESS_c if deallocation was successful, MEM_FREE_ERROR_c if not.
andreikovacs 0:764779eedf2d 330 *
andreikovacs 0:764779eedf2d 331 * \pre Memory manager must be previously initialized.
andreikovacs 0:764779eedf2d 332 *
andreikovacs 0:764779eedf2d 333 * \remarks Never deallocate the same buffer twice.
andreikovacs 0:764779eedf2d 334 *
andreikovacs 0:764779eedf2d 335 ********************************************************************************** */
andreikovacs 0:764779eedf2d 336 memStatus_t MEM_BufferFree
andreikovacs 0:764779eedf2d 337 (
andreikovacs 0:764779eedf2d 338 void* buffer // IN: Block of memory to free
andreikovacs 0:764779eedf2d 339 )
andreikovacs 0:764779eedf2d 340 {
andreikovacs 0:764779eedf2d 341 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 342
andreikovacs 0:764779eedf2d 343 /* Save the Link Register */
andreikovacs 0:764779eedf2d 344 volatile uint32_t savedLR;
andreikovacs 0:764779eedf2d 345 // __asm("str r14, [SP]");
andreikovacs 0:764779eedf2d 346 __asm("push {r1} ");
andreikovacs 0:764779eedf2d 347 __asm("push {LR} ");
andreikovacs 0:764779eedf2d 348 __asm("pop {r1} ");
andreikovacs 0:764779eedf2d 349 __asm("str r1, [SP, #4]");
andreikovacs 0:764779eedf2d 350 __asm("pop {r1}");
andreikovacs 0:764779eedf2d 351 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 352
andreikovacs 0:764779eedf2d 353 if(buffer == NULL)
andreikovacs 0:764779eedf2d 354 {
andreikovacs 0:764779eedf2d 355 return MEM_FREE_ERROR_c;
andreikovacs 0:764779eedf2d 356 }
andreikovacs 0:764779eedf2d 357
andreikovacs 0:764779eedf2d 358 OSA_EnterCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 359
andreikovacs 0:764779eedf2d 360 listHeader_t *pHeader = (listHeader_t *)buffer-1;
andreikovacs 0:764779eedf2d 361 pools_t *pParentPool = (pools_t *)pHeader->pParentPool;
andreikovacs 0:764779eedf2d 362
andreikovacs 0:764779eedf2d 363 pools_t *pool = memPools;
andreikovacs 0:764779eedf2d 364 for(;;)
andreikovacs 0:764779eedf2d 365 {
andreikovacs 0:764779eedf2d 366 if (pParentPool == pool)
andreikovacs 0:764779eedf2d 367 break;
andreikovacs 0:764779eedf2d 368 if(pool->nextBlockSize == 0)
andreikovacs 0:764779eedf2d 369 {
andreikovacs 0:764779eedf2d 370 /* The parent pool was not found! This means that the memory buffer is corrupt or
andreikovacs 0:764779eedf2d 371 that the MEM_BufferFree() function was called with an invalid parameter */
andreikovacs 0:764779eedf2d 372 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 373 pParentPool->poolStatistics.freeFailures++;
andreikovacs 0:764779eedf2d 374 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 375 OSA_ExitCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 376 return MEM_FREE_ERROR_c;
andreikovacs 0:764779eedf2d 377 }
andreikovacs 0:764779eedf2d 378 pool++;
andreikovacs 0:764779eedf2d 379 }
andreikovacs 0:764779eedf2d 380
andreikovacs 0:764779eedf2d 381 if( pHeader->link.list != NULL )
andreikovacs 0:764779eedf2d 382 {
andreikovacs 0:764779eedf2d 383 /* The memory buffer appears to be enqueued in a linked list.
andreikovacs 0:764779eedf2d 384 This list may be the free memory buffers pool, or another list. */
andreikovacs 0:764779eedf2d 385 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 386 pParentPool->poolStatistics.freeFailures++;
andreikovacs 0:764779eedf2d 387 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 388 OSA_ExitCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 389 return MEM_FREE_ERROR_c;
andreikovacs 0:764779eedf2d 390 }
andreikovacs 0:764779eedf2d 391
andreikovacs 0:764779eedf2d 392 gFreeMessagesCount++;
andreikovacs 0:764779eedf2d 393
andreikovacs 0:764779eedf2d 394 ListAddTail((listHandle_t)&pParentPool->anchor, (listElementHandle_t)&pHeader->link);
andreikovacs 0:764779eedf2d 395
andreikovacs 0:764779eedf2d 396 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 397 MEM_ASSERT(pParentPool->poolStatistics.allocatedBlocks > 0);
andreikovacs 0:764779eedf2d 398 pParentPool->poolStatistics.allocatedBlocks--;
andreikovacs 0:764779eedf2d 399 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 400
andreikovacs 0:764779eedf2d 401 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 402 MEM_Track(buffer, MEM_TRACKING_FREE_c, savedLR, 0);
andreikovacs 0:764779eedf2d 403 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 404 OSA_ExitCritical(kCriticalDisableInt);
andreikovacs 0:764779eedf2d 405 return MEM_SUCCESS_c;
andreikovacs 0:764779eedf2d 406 }
andreikovacs 0:764779eedf2d 407
andreikovacs 0:764779eedf2d 408 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 409 * \brief Determines the size of a memory block
andreikovacs 0:764779eedf2d 410 *
andreikovacs 0:764779eedf2d 411 * \param[in] buffer - Pointer to buffer.
andreikovacs 0:764779eedf2d 412 *
andreikovacs 0:764779eedf2d 413 * \return size of memory block
andreikovacs 0:764779eedf2d 414 *
andreikovacs 0:764779eedf2d 415 * \pre Memory manager must be previously initialized.
andreikovacs 0:764779eedf2d 416 *
andreikovacs 0:764779eedf2d 417 ********************************************************************************** */
andreikovacs 0:764779eedf2d 418 uint16_t MEM_BufferGetSize
andreikovacs 0:764779eedf2d 419 (
andreikovacs 0:764779eedf2d 420 void* buffer // IN: Block of memory to free
andreikovacs 0:764779eedf2d 421 )
andreikovacs 0:764779eedf2d 422 {
andreikovacs 0:764779eedf2d 423 if( buffer )
andreikovacs 0:764779eedf2d 424 {
andreikovacs 0:764779eedf2d 425 return ((pools_t *)((listHeader_t *)buffer-1)->pParentPool)->blockSize;
andreikovacs 0:764779eedf2d 426 }
andreikovacs 0:764779eedf2d 427
andreikovacs 0:764779eedf2d 428 return 0;
andreikovacs 0:764779eedf2d 429 }
andreikovacs 0:764779eedf2d 430
andreikovacs 0:764779eedf2d 431 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 432 *************************************************************************************
andreikovacs 0:764779eedf2d 433 * Private functions
andreikovacs 0:764779eedf2d 434 *************************************************************************************
andreikovacs 0:764779eedf2d 435 ********************************************************************************** */
andreikovacs 0:764779eedf2d 436 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 437 * \brief This function updates the tracking array element corresponding to the given
andreikovacs 0:764779eedf2d 438 * block.
andreikovacs 0:764779eedf2d 439 *
andreikovacs 0:764779eedf2d 440 * \param[in] block - Pointer to the block.
andreikovacs 0:764779eedf2d 441 * \param[in] alloc - Indicates whether an allocation or free operation was performed
andreikovacs 0:764779eedf2d 442 * \param[in] address - Address where MEM_BufferAlloc or MEM_BufferFree was called
andreikovacs 0:764779eedf2d 443 * \param[in] requestedSize - Indicates the requested buffer size passed to MEM_BufferAlloc.
andreikovacs 0:764779eedf2d 444 * Has no use if a free operation was performed.
andreikovacs 0:764779eedf2d 445 *
andreikovacs 0:764779eedf2d 446 * \return Returns TRUE if correct allocation or dealocation was performed, FALSE if a
andreikovacs 0:764779eedf2d 447 * buffer was allocated or freed twice.
andreikovacs 0:764779eedf2d 448 *
andreikovacs 0:764779eedf2d 449 ********************************************************************************** */
andreikovacs 0:764779eedf2d 450 #ifdef MEM_TRACKING
andreikovacs 0:764779eedf2d 451 uint8_t MEM_Track(listHeader_t *block, memTrackingStatus_t alloc, uint32_t address, uint16_t requestedSize)
andreikovacs 0:764779eedf2d 452 {
andreikovacs 0:764779eedf2d 453 uint16_t i;
andreikovacs 0:764779eedf2d 454 blockTracking_t *pTrack = NULL;
andreikovacs 0:764779eedf2d 455 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 456 poolStat_t * poolStatistics = (poolStat_t *)&((pools_t *)( (listElementHandle_t)(block-1)->pParentPool ))->poolStatistics;
andreikovacs 0:764779eedf2d 457 #endif
andreikovacs 0:764779eedf2d 458
andreikovacs 0:764779eedf2d 459 for( i=0; i<mTotalNoOfMsgs_c; i++ )
andreikovacs 0:764779eedf2d 460 {
andreikovacs 0:764779eedf2d 461 if( block == memTrack[i].blockAddr )
andreikovacs 0:764779eedf2d 462 {
andreikovacs 0:764779eedf2d 463 pTrack = &memTrack[i];
andreikovacs 0:764779eedf2d 464 break;
andreikovacs 0:764779eedf2d 465 }
andreikovacs 0:764779eedf2d 466 }
andreikovacs 0:764779eedf2d 467
andreikovacs 0:764779eedf2d 468 if( !pTrack || pTrack->allocStatus == alloc)
andreikovacs 0:764779eedf2d 469 {
andreikovacs 0:764779eedf2d 470 #ifdef MEM_DEBUG
andreikovacs 0:764779eedf2d 471 panic( 0, (uint32_t)MEM_Track, 0, 0);
andreikovacs 0:764779eedf2d 472 #endif
andreikovacs 0:764779eedf2d 473 return FALSE;
andreikovacs 0:764779eedf2d 474 }
andreikovacs 0:764779eedf2d 475
andreikovacs 0:764779eedf2d 476 pTrack->allocStatus = alloc;
andreikovacs 0:764779eedf2d 477
andreikovacs 0:764779eedf2d 478 if(alloc == MEM_TRACKING_ALLOC_c)
andreikovacs 0:764779eedf2d 479 {
andreikovacs 0:764779eedf2d 480 pTrack->fragmentWaste = pTrack->blockSize - requestedSize;
andreikovacs 0:764779eedf2d 481 pTrack->allocCounter++;
andreikovacs 0:764779eedf2d 482 pTrack->allocAddr = (void *)address;
andreikovacs 0:764779eedf2d 483 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 484
andreikovacs 0:764779eedf2d 485 poolStatistics->poolFragmentWaste += pTrack->fragmentWaste;
andreikovacs 0:764779eedf2d 486 if(poolStatistics->poolFragmentWaste > poolStatistics->poolFragmentWastePeak)
andreikovacs 0:764779eedf2d 487 poolStatistics->poolFragmentWastePeak = poolStatistics->poolFragmentWaste;
andreikovacs 0:764779eedf2d 488 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 489 }
andreikovacs 0:764779eedf2d 490 else
andreikovacs 0:764779eedf2d 491 {
andreikovacs 0:764779eedf2d 492 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 493 poolStatistics->poolFragmentWaste -= pTrack->fragmentWaste;
andreikovacs 0:764779eedf2d 494 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 495 pTrack->fragmentWaste = 0;
andreikovacs 0:764779eedf2d 496 pTrack->freeCounter++;
andreikovacs 0:764779eedf2d 497 pTrack->freeAddr = (void *)address;
andreikovacs 0:764779eedf2d 498 }
andreikovacs 0:764779eedf2d 499
andreikovacs 0:764779eedf2d 500 return TRUE;
andreikovacs 0:764779eedf2d 501 }
andreikovacs 0:764779eedf2d 502
andreikovacs 0:764779eedf2d 503 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 504 * \brief This function checks for buffer overflow when copying multiple bytes
andreikovacs 0:764779eedf2d 505 *
andreikovacs 0:764779eedf2d 506 * \param[in] p - pointer to destination.
andreikovacs 0:764779eedf2d 507 * \param[in] size - number of bytes to copy
andreikovacs 0:764779eedf2d 508 *
andreikovacs 0:764779eedf2d 509 * \return 1 if overflow detected, else 0
andreikovacs 0:764779eedf2d 510 *
andreikovacs 0:764779eedf2d 511 ********************************************************************************** */
andreikovacs 0:764779eedf2d 512 uint8_t MEM_BufferCheck(uint8_t *p, uint32_t size)
andreikovacs 0:764779eedf2d 513 {
andreikovacs 0:764779eedf2d 514 uint32_t i;
andreikovacs 0:764779eedf2d 515
andreikovacs 0:764779eedf2d 516 if( (p < (uint8_t*)memHeap) || (p > ((uint8_t*)memHeap + sizeof(memHeap))) )
andreikovacs 0:764779eedf2d 517 return 0;
andreikovacs 0:764779eedf2d 518
andreikovacs 0:764779eedf2d 519 for(i=0; i<mTotalNoOfMsgs_c-1; i++)
andreikovacs 0:764779eedf2d 520 {
andreikovacs 0:764779eedf2d 521 if( p > (uint8_t*)memTrack[i].blockAddr &&
andreikovacs 0:764779eedf2d 522 p < (uint8_t*)memTrack[i+1].blockAddr )
andreikovacs 0:764779eedf2d 523 {
andreikovacs 0:764779eedf2d 524 if( (p+size) > ((uint8_t*)memTrack[i+1].blockAddr - sizeof(listHeader_t)) )
andreikovacs 0:764779eedf2d 525 {
andreikovacs 0:764779eedf2d 526 #ifdef MEM_DEBUG
andreikovacs 0:764779eedf2d 527 panic(0,0,0,0);
andreikovacs 0:764779eedf2d 528 #endif
andreikovacs 0:764779eedf2d 529 return 1;
andreikovacs 0:764779eedf2d 530 }
andreikovacs 0:764779eedf2d 531
andreikovacs 0:764779eedf2d 532 break;
andreikovacs 0:764779eedf2d 533 }
andreikovacs 0:764779eedf2d 534 }
andreikovacs 0:764779eedf2d 535 return 0;
andreikovacs 0:764779eedf2d 536 }
andreikovacs 0:764779eedf2d 537 #endif /*MEM_TRACKING*/
andreikovacs 0:764779eedf2d 538
andreikovacs 0:764779eedf2d 539 /*! *********************************************************************************
andreikovacs 0:764779eedf2d 540 * \brief Performs a write-read-verify test for every byte in all memory pools.
andreikovacs 0:764779eedf2d 541 *
andreikovacs 0:764779eedf2d 542 * \return Returns MEM_SUCCESS_c if test was successful, MEM_ALLOC_ERROR_c if a
andreikovacs 0:764779eedf2d 543 * buffer was not allocated successufuly, MEM_FREE_ERROR_c if a
andreikovacs 0:764779eedf2d 544 * buffer was not freed successufuly or MEM_UNKNOWN_ERROR_c if a verify error,
andreikovacs 0:764779eedf2d 545 * heap overflow or data corruption occurred.
andreikovacs 0:764779eedf2d 546 *
andreikovacs 0:764779eedf2d 547 ********************************************************************************** */
andreikovacs 0:764779eedf2d 548 uint32_t MEM_WriteReadTest(void)
andreikovacs 0:764779eedf2d 549 {
andreikovacs 0:764779eedf2d 550 uint8_t *data, count = 1;
andreikovacs 0:764779eedf2d 551 uint32_t idx1,idx2,idx3;
andreikovacs 0:764779eedf2d 552 uint32_t freeMsgs;
andreikovacs 0:764779eedf2d 553
andreikovacs 0:764779eedf2d 554 /*memory write test*/
andreikovacs 0:764779eedf2d 555 freeMsgs = MEM_GetAvailableBlocks(0);
andreikovacs 0:764779eedf2d 556
andreikovacs 0:764779eedf2d 557 for(idx1=0; poolInfo[idx1].blockSize != 0; idx1++)
andreikovacs 0:764779eedf2d 558 {
andreikovacs 0:764779eedf2d 559 for(idx2=0; idx2 < poolInfo[idx1].poolSize; idx2++)
andreikovacs 0:764779eedf2d 560 {
andreikovacs 0:764779eedf2d 561 data = (uint8_t *)MEM_BufferAlloc(poolInfo[idx1].blockSize);
andreikovacs 0:764779eedf2d 562
andreikovacs 0:764779eedf2d 563 if(data == NULL)
andreikovacs 0:764779eedf2d 564 {
andreikovacs 0:764779eedf2d 565 return MEM_ALLOC_ERROR_c;
andreikovacs 0:764779eedf2d 566 }
andreikovacs 0:764779eedf2d 567
andreikovacs 0:764779eedf2d 568 for(idx3=0; idx3 < poolInfo[idx1].blockSize; idx3++)
andreikovacs 0:764779eedf2d 569 {
andreikovacs 0:764779eedf2d 570 if(data > memHeap + heapSize)
andreikovacs 0:764779eedf2d 571 {
andreikovacs 0:764779eedf2d 572 return MEM_UNKNOWN_ERROR_c;
andreikovacs 0:764779eedf2d 573 }
andreikovacs 0:764779eedf2d 574 *data = count & 0xff;
andreikovacs 0:764779eedf2d 575 data++;
andreikovacs 0:764779eedf2d 576 }
andreikovacs 0:764779eedf2d 577 count++;
andreikovacs 0:764779eedf2d 578 }
andreikovacs 0:764779eedf2d 579 }
andreikovacs 0:764779eedf2d 580
andreikovacs 0:764779eedf2d 581 count = 1;
andreikovacs 0:764779eedf2d 582 data = memHeap;
andreikovacs 0:764779eedf2d 583 /*memory read test*/
andreikovacs 0:764779eedf2d 584 for(idx1=0; poolInfo[idx1].blockSize != 0; idx1++)
andreikovacs 0:764779eedf2d 585 {
andreikovacs 0:764779eedf2d 586 for(idx2=0; idx2 < poolInfo[idx1].poolSize; idx2++)
andreikovacs 0:764779eedf2d 587 {
andreikovacs 0:764779eedf2d 588 /*New block; jump over list header*/
andreikovacs 0:764779eedf2d 589 data = data + sizeof(listHeader_t);
andreikovacs 0:764779eedf2d 590 for(idx3=0; idx3<poolInfo[idx1].blockSize; idx3++)
andreikovacs 0:764779eedf2d 591 {
andreikovacs 0:764779eedf2d 592 if(*data == count)
andreikovacs 0:764779eedf2d 593 {
andreikovacs 0:764779eedf2d 594 data++;
andreikovacs 0:764779eedf2d 595 }
andreikovacs 0:764779eedf2d 596 else
andreikovacs 0:764779eedf2d 597 {
andreikovacs 0:764779eedf2d 598 return MEM_UNKNOWN_ERROR_c;
andreikovacs 0:764779eedf2d 599 }
andreikovacs 0:764779eedf2d 600 }
andreikovacs 0:764779eedf2d 601 if(MEM_BufferFree( data - poolInfo[idx1].blockSize) != MEM_SUCCESS_c)
andreikovacs 0:764779eedf2d 602 {
andreikovacs 0:764779eedf2d 603 return MEM_FREE_ERROR_c;
andreikovacs 0:764779eedf2d 604 }
andreikovacs 0:764779eedf2d 605 count++;
andreikovacs 0:764779eedf2d 606 }
andreikovacs 0:764779eedf2d 607 }
andreikovacs 0:764779eedf2d 608 if(MEM_GetAvailableBlocks(0) != freeMsgs)
andreikovacs 0:764779eedf2d 609 {
andreikovacs 0:764779eedf2d 610 return MEM_UNKNOWN_ERROR_c;
andreikovacs 0:764779eedf2d 611 }
andreikovacs 0:764779eedf2d 612 #ifdef MEM_STATISTICS
andreikovacs 0:764779eedf2d 613 for(idx1 = 0; poolInfo[idx1].blockSize != 0; idx1++)
andreikovacs 0:764779eedf2d 614 {
andreikovacs 0:764779eedf2d 615 memPools[idx1].poolStatistics.allocatedBlocksPeak = 0;
andreikovacs 0:764779eedf2d 616 }
andreikovacs 0:764779eedf2d 617 #endif /*MEM_STATISTICS*/
andreikovacs 0:764779eedf2d 618
andreikovacs 0:764779eedf2d 619 return MEM_SUCCESS_c;
andreikovacs 0:764779eedf2d 620 }