electronix79
/
CoOS_mbed
CooCox 1.1.4 on mbed with simple blinky example
Embed:
(wiki syntax)
Show/hide line numbers
kernelHeap.c
Go to the documentation of this file.
00001 /** 00002 ******************************************************************************* 00003 * @file kernelHeap.c 00004 * @version V1.1.4 00005 * @date 2011.04.20 00006 * @brief kernel heap management implementation code of CooCox CoOS kernel. 00007 ******************************************************************************* 00008 * @copy 00009 * 00010 * INTERNAL FILE,DON'T PUBLIC. 00011 * 00012 * <h2><center>© COPYRIGHT 2009 CooCox </center></h2> 00013 ******************************************************************************* 00014 */ 00015 00016 00017 /*---------------------------- Include ---------------------------------------*/ 00018 #include <coocox.h> 00019 00020 00021 #if CFG_KHEAP_EN >0 00022 /*---------------------------- Variable Define -------------------------------*/ 00023 U32 KernelHeap [KHEAP_SIZE] = {0}; /*!< Kernel heap */ 00024 P_FMB FMBlist = Co_NULL; /*!< Free memory block list */ 00025 KHeap Kheap = {0}; /*!< Kernel heap control */ 00026 00027 00028 /*---------------------------- Function Declare ------------------------------*/ 00029 static P_FMB GetPreFMB(P_UMB usedMB); 00030 /** 00031 ******************************************************************************* 00032 * @brief Create kernel heap 00033 * @param[in] None 00034 * @param[out] None 00035 * @retval None 00036 * 00037 * @par Description 00038 * @details This function is called to create kernel heap. 00039 ******************************************************************************* 00040 */ 00041 void CoCreateKheap(void) 00042 { 00043 Kheap .startAddr = (U32)(KernelHeap ); /* Initialize kernel heap control */ 00044 Kheap .endAddr = (U32)(KernelHeap ) + KHEAP_SIZE*4; 00045 FMBlist = (P_FMB)KernelHeap ; /* Initialize free memory block list*/ 00046 FMBlist ->nextFMB = Co_NULL; 00047 FMBlist ->nextUMB = Co_NULL; 00048 FMBlist ->preUMB = Co_NULL; 00049 } 00050 00051 00052 /** 00053 ******************************************************************************* 00054 * @brief Allocation size bytes of memory block from kernel heap. 00055 * @param[in] size Length of menory block. 00056 * @param[out] None 00057 * @retval Co_NULL Allocate fail. 00058 * @retval others Pointer to memory block. 00059 * 00060 * @par Description 00061 * @details This function is called to allocation size bytes of memory block. 00062 ******************************************************************************* 00063 */ 00064 void* CoKmalloc(U32 size) 00065 { 00066 P_FMB freeMB,newFMB,preFMB; 00067 P_UMB usedMB,tmpUMB; 00068 U8* memAddr; 00069 U32 freeSize; 00070 U32 kheapAddr; 00071 00072 #if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ 00073 if( size == 0 ) 00074 { 00075 return Co_NULL; 00076 } 00077 #endif 00078 00079 /* Word alignment,and add used memory head size */ 00080 size = (((size+3)>>2)<<2) + 8; 00081 kheapAddr = Kheap .endAddr; /* Get the end address of kernel heap */ 00082 OsSchedLock(); /* Lock schedule */ 00083 freeMB = FMBlist ; /* Get first item of free memory list */ 00084 preFMB = Co_NULL; 00085 while(freeMB != Co_NULL ) /* Is out of free memory list? */ 00086 { /* No */ 00087 if(freeMB->nextUMB == Co_NULL) /* Is last item of free memory list? */ 00088 { /* Yes,get size for this free item */ 00089 freeSize = kheapAddr - (U32)(freeMB); 00090 } 00091 else /* No,get size for this free item */ 00092 { 00093 freeSize = (U32)(freeMB->nextUMB) -1 - (U32)(freeMB); 00094 } 00095 if(freeSize >= size) /* If the size equal or greater than need */ 00096 { /* Yes,assign in this free memory */ 00097 usedMB=(P_UMB)freeMB;/* Get the address for used memory block head*/ 00098 00099 /* Get the address for used memory block */ 00100 memAddr = (U8*)((U32)(usedMB) + 8); 00101 00102 /* Is left size of free memory smaller than 12? */ 00103 if((freeSize-size) < 12) 00104 { 00105 /* Yes,malloc together(12 is the size of the header information 00106 of free memory block ). */ 00107 if(preFMB != Co_NULL)/* Is first item of free memory block list? */ 00108 { /* No,set the link for list */ 00109 preFMB->nextFMB = freeMB->nextFMB; 00110 } 00111 else /* Yes,reset the first item */ 00112 { 00113 FMBlist = freeMB->nextFMB; 00114 } 00115 00116 if(freeMB->nextUMB != Co_NULL) /* Is last item? */ 00117 { /* No,set the link for list */ 00118 tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1); 00119 tmpUMB->preMB = (void*)((U32)usedMB|0x1); 00120 } 00121 00122 usedMB->nextMB = freeMB->nextUMB;/* Set used memory block link*/ 00123 usedMB->preMB = freeMB->preUMB; 00124 } 00125 else /* No,the left size more than 12 */ 00126 { 00127 /* Get new free memory block address */ 00128 newFMB = (P_FMB)((U32)(freeMB) + size); 00129 00130 if(preFMB != Co_NULL)/* Is first item of free memory block list? */ 00131 { 00132 preFMB->nextFMB = newFMB; /* No,set the link for list */ 00133 } 00134 else 00135 { 00136 FMBlist = newFMB; /* Yes,reset the first item */ 00137 } 00138 00139 /* Set link for new free memory block */ 00140 newFMB->preUMB = (P_UMB)((U32)usedMB|0x1); 00141 newFMB->nextUMB = freeMB->nextUMB; 00142 newFMB->nextFMB = freeMB->nextFMB; 00143 00144 if(freeMB->nextUMB != Co_NULL) /* Is last item? */ 00145 { /* No,set the link for list */ 00146 tmpUMB = (P_UMB)((U32)(freeMB->nextUMB)-1); 00147 tmpUMB->preMB = newFMB; 00148 } 00149 00150 usedMB->nextMB = newFMB; /* Set used memory block link */ 00151 usedMB->preMB = freeMB->preUMB; 00152 } 00153 00154 if(freeMB->preUMB != Co_NULL) /* Is first item? */ 00155 { /* No,set the link for list */ 00156 tmpUMB = (P_UMB)((U32)(freeMB->preUMB)-1); 00157 tmpUMB->nextMB = (void*)((U32)usedMB|0x1); 00158 } 00159 00160 OsSchedUnlock(); /* Unlock schedule */ 00161 return memAddr; /* Return used memory block address */ 00162 } 00163 preFMB = freeMB; /* Save current free memory block as previous */ 00164 freeMB = freeMB->nextFMB; /* Get the next item as current item*/ 00165 } 00166 OsSchedUnlock(); /* Unlock schedule */ 00167 return Co_NULL; /* Error return */ 00168 } 00169 00170 00171 /** 00172 ******************************************************************************* 00173 * @brief Release memory block to kernel heap. 00174 * @param[in] memBuf Pointer to memory block. 00175 * @param[out] None 00176 * @retval None 00177 * 00178 * @par Description 00179 * @details This function is called to release memory block. 00180 ******************************************************************************* 00181 */ 00182 void CoKfree(void* memBuf) 00183 { 00184 P_FMB curFMB,nextFMB,preFMB; 00185 P_UMB usedMB,nextUMB,preUMB; 00186 00187 #if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ 00188 if(memBuf == Co_NULL) 00189 { 00190 return; 00191 } 00192 #endif 00193 00194 usedMB = (P_UMB)((U32)(memBuf)-8); 00195 00196 #if CFG_PAR_CHECKOUT_EN >0 /* Check validity of parameter */ 00197 if((U32)(memBuf) < Kheap .startAddr) 00198 { 00199 return; 00200 } 00201 if((U32)(memBuf) > Kheap .endAddr) 00202 { 00203 return; 00204 } 00205 #endif 00206 00207 00208 OsSchedLock(); /* Lock schedule */ 00209 00210 #if CFG_PAR_CHECKOUT_EN >0 /* Check UMB in list */ 00211 if((U32)(usedMB) < (U32)(FMBlist )) 00212 { 00213 preUMB = (P_UMB)((U32)(FMBlist ->preUMB)-1); 00214 while(preUMB != usedMB) 00215 { 00216 if(preUMB == Co_NULL) 00217 { 00218 OsSchedUnlock(); 00219 return; 00220 } 00221 preUMB = (P_UMB)((U32)(preUMB->preMB)-1); 00222 } 00223 } 00224 else 00225 { 00226 if(FMBlist == Co_NULL) 00227 { 00228 nextUMB = (P_UMB)(Kheap .startAddr); 00229 } 00230 else 00231 { 00232 if(FMBlist ->nextUMB != Co_NULL) 00233 { 00234 nextUMB = (P_UMB)((U32)(FMBlist ->nextUMB)-1); 00235 } 00236 else 00237 { 00238 nextUMB = Co_NULL; 00239 } 00240 } 00241 00242 while(nextUMB != usedMB) 00243 { 00244 if(nextUMB == Co_NULL) 00245 { 00246 OsSchedUnlock(); 00247 return; 00248 } 00249 if(((U32)(nextUMB->nextMB)&0x1) == 0) 00250 { 00251 nextFMB = (P_FMB)(nextUMB->nextMB); 00252 nextUMB = (P_UMB)((U32)(nextFMB->nextUMB)-1); 00253 } 00254 else 00255 { 00256 nextUMB = (P_UMB)((U32)(nextUMB->nextMB)-1); 00257 } 00258 } 00259 } 00260 #endif 00261 00262 00263 /* Is between two free memory block? */ 00264 if( (((U32)(usedMB->nextMB)&0x1) == 0) && (((U32)(usedMB->preMB)&0x1)==0) ) 00265 { /* Yes,is the only one item in kernel heap? */ 00266 if((usedMB->nextMB == Co_NULL) && (usedMB->preMB == Co_NULL)) 00267 { 00268 curFMB = (P_FMB)usedMB; /* Yes,release this item */ 00269 curFMB->nextFMB = Co_NULL; 00270 curFMB->nextUMB = Co_NULL; 00271 curFMB->preUMB = Co_NULL; 00272 FMBlist = curFMB; 00273 } 00274 else if(usedMB->preMB == Co_NULL) /* Is the first item in kernel heap */ 00275 { 00276 /* Yes,release this item,and set link for list */ 00277 curFMB = (P_FMB)usedMB; 00278 nextFMB = (P_FMB)usedMB->nextMB; 00279 00280 curFMB->nextFMB = nextFMB->nextFMB; 00281 curFMB->nextUMB = nextFMB->nextUMB; 00282 curFMB->preUMB = Co_NULL; 00283 FMBlist = curFMB; 00284 } 00285 else if(usedMB->nextMB == Co_NULL) /* Is the last item in kernel heap */ 00286 { /* Yes,release this item,and set link for list */ 00287 curFMB = (P_FMB)(usedMB->preMB); 00288 curFMB->nextFMB = Co_NULL; 00289 curFMB->nextUMB = Co_NULL; 00290 } 00291 else /* All no,show this item between two normal FMB */ 00292 { 00293 /* release this item,and set link for list */ 00294 nextFMB = (P_FMB)usedMB->nextMB; 00295 curFMB = (P_FMB)(usedMB->preMB); 00296 00297 curFMB->nextFMB = nextFMB->nextFMB; 00298 curFMB->nextUMB = nextFMB->nextUMB; 00299 } 00300 } 00301 else if(((U32)(usedMB->preMB)&0x1) == 0) /* Is between FMB and UMB? */ 00302 { 00303 if(usedMB->preMB == Co_NULL) /* Yes,is the first item in kernel heap? */ 00304 { 00305 /* Yes,release this item,and set link for list */ 00306 curFMB = (P_FMB)usedMB; 00307 nextUMB = (P_UMB)usedMB->nextMB; 00308 curFMB->nextUMB = nextUMB; 00309 curFMB->preUMB = Co_NULL; 00310 curFMB->nextFMB = FMBlist ; 00311 FMBlist = curFMB; 00312 } 00313 else /* No,release this item,and set link for list */ 00314 { 00315 curFMB = (P_FMB)usedMB->preMB; 00316 nextUMB = (P_UMB)usedMB->nextMB; 00317 curFMB->nextUMB = nextUMB; 00318 } 00319 00320 } 00321 else if(((U32)(usedMB->nextMB)&0x1) == 0) /* Is between UMB and FMB? */ 00322 { /* Yes */ 00323 preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */ 00324 curFMB = (P_FMB)(usedMB); /* new FMB */ 00325 preFMB = GetPreFMB(usedMB); /* Get previous FMB */ 00326 if(preFMB == Co_NULL) /* Is previous FMB==Co_NULL? */ 00327 { 00328 nextFMB = FMBlist ; /* Yes,get next FMB */ 00329 FMBlist = curFMB; /* Reset new FMB as the first item of FMB list*/ 00330 } 00331 else 00332 { 00333 nextFMB = preFMB->nextFMB; /* No,get next FMB */ 00334 preFMB->nextFMB = curFMB; /* Set link for FMB list */ 00335 } 00336 00337 if(nextFMB == Co_NULL) /* Is new FMB as last item of FMB list? */ 00338 { 00339 curFMB->preUMB = preUMB; /* Yes,set link for list */ 00340 curFMB->nextUMB = Co_NULL; 00341 curFMB->nextFMB = Co_NULL; 00342 } 00343 else 00344 { 00345 curFMB->preUMB = preUMB; /* No,set link for list */ 00346 curFMB->nextUMB = nextFMB->nextUMB; 00347 curFMB->nextFMB = nextFMB->nextFMB; 00348 } 00349 } 00350 else /* All no,show UMB between two UMB*/ 00351 { 00352 curFMB = (P_FMB)(usedMB); /* new FMB */ 00353 preFMB = GetPreFMB(usedMB); /* Get previous FMB */ 00354 preUMB = (P_UMB)(usedMB->preMB); /* Get previous UMB */ 00355 nextUMB = (P_UMB)(usedMB->nextMB); /* Get next UMB */ 00356 00357 if(preFMB == Co_NULL ) /* Is previous FMB==Co_NULL? */ 00358 { 00359 nextFMB = FMBlist ; /* Yes,get next FMB */ 00360 FMBlist = curFMB; /* Reset new FMB as the first item of FMB list */ 00361 } 00362 else 00363 { 00364 nextFMB = preFMB->nextFMB; /* No,get next FMB */ 00365 preFMB->nextFMB = curFMB; /* Set link for FMB list */ 00366 } 00367 00368 curFMB->preUMB = preUMB; /* Set current FMB link for list */ 00369 curFMB->nextUMB = nextUMB; 00370 curFMB->nextFMB = nextFMB; 00371 } 00372 00373 if(curFMB->preUMB != Co_NULL)/* Is current FMB as first item in kernel heap? */ 00374 { /* No,set link for list */ 00375 preUMB = (P_UMB)((U32)(curFMB->preUMB)-1); 00376 preUMB->nextMB = (void*)curFMB; 00377 } 00378 if(curFMB->nextUMB != Co_NULL)/* Is current FMB as last item in kernel heap? */ 00379 { /* No,set link for list */ 00380 nextUMB = (P_UMB)((U32)(curFMB->nextUMB)-1); 00381 nextUMB->preMB = (void*)curFMB; 00382 } 00383 OsSchedUnlock(); /* Unlock schedule */ 00384 } 00385 00386 00387 /** 00388 ******************************************************************************* 00389 * @brief Get previous free memory block pointer. 00390 * @param[in] usedMB Current used memory block. 00391 * @param[out] None 00392 * @retval Previous free memory block pointer. 00393 * 00394 * @par Description 00395 * @details This function is called to get previous free memory block pointer. 00396 ******************************************************************************* 00397 */ 00398 static P_FMB GetPreFMB(P_UMB usedMB) 00399 { 00400 P_UMB preUMB; 00401 preUMB = usedMB; 00402 while(((U32)(preUMB->preMB)&0x1)) /* Is previous MB as FMB? */ 00403 { /* No,get previous MB */ 00404 preUMB = (P_UMB)((U32)(preUMB->preMB)-1); 00405 } 00406 return (P_FMB)(preUMB->preMB); /* Yes,return previous MB */ 00407 } 00408 00409 #endif
Generated on Tue Jul 12 2022 18:19:10 by 1.7.2