CooCox 1.1.4 on mbed with simple blinky example

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers kernelHeap.c Source File

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>&copy; 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