1 / 13

Chapter 12 Memory Management

Chapter 12 Memory Management. The dynamic memory allocation can be achieved by using malloc() and free() function Using malloc() and free(0 in an embedded real-time system is dangerous Eventually may incur fragmentation Execution time of malloc() and free(0) are nondeterministic

meg
Download Presentation

Chapter 12 Memory Management

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 12Memory Management

  2. The dynamic memory allocation can be achieved by using malloc() and free() function • Using malloc() and free(0 in an embedded real-time system is dangerous • Eventually may incur fragmentation • Execution time of malloc() and free(0) are nondeterministic • uC/OS-II provides fixed-sized memory blocks from partition made of a contiguous memory • Allocation and deallocation of these memory blocks is done in constant time and is deterministic • Memory service: OSMemCreate(0, OSMemGet(), OSMemPut(), OSMemQuery() Figure 7.1 memory partition Figure 7.2 multiple memory partitions

  3. Memory control block data structure • The memory partitions is maintained by memory control block typedef struct { void *OSMemAddr; //point to the beginning of memory block void *OSMemFreeList; //point to MCB or memory block INT32U OSMemBlkSize; INT32U OSMemNBlks; //total memory blocks INT32U OSMemNFree; //current available memory blocks } OS_MEM; List of free memory control blocks

  4. 12.01 Creating a partition, OSMemCreate() OS_MEM *CommTxBuf; INT8U CommTxPart[100][32]; void main (void) { INT8U err; OSInit(); . . CommTxBuf = OSMemCreate(CommTxPart, 100, 32, &err); . . OSStart(); } • Four arguments are required • Beginning address of the memory partition • The number of blocks to be allocated from this partition • The size (in bytes) of each block • A pointer to a variable that contains an error code

  5. OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err) { OS_MEM *pmem; INT8U *pblk; void **plink; INT32U i; if (nblks < 2) { //each memory partition must contain at least two memory blocks (1) *err = OS_MEM_INVALID_BLKS; return ((OS_MEM *)0); } if (blksize < sizeof(void *)) { //each memory block must be able to hold the size of a pointer (2) *err = OS_MEM_INVALID_SIZE; return ((OS_MEM *)0); } OS_ENTER_CRITICAL(); pmem = OSMemFreeList; //obtain a MCB (3) if (OSMemFreeList != (OS_MEM *)0) { OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList; } OS_EXIT_CRITICAL(); if (pmem == (OS_MEM *)0) { (4) *err = OS_MEM_INVALID_PART; return ((OS_MEM *)0); } OSMemCrate(): return MCB address or 0

  6. plink = (void **)addr; (5) pblk = (INT8U *)addr + blksize; for (i = 0; i < (nblks - 1); i++) { *plink = (void *)pblk; plink = (void **)pblk; pblk = pblk + blksize; } *plink = (void *)0; OS_ENTER_CRITICAL(); pmem->OSMemAddr = addr; (6) pmem->OSMemFreeList = addr; pmem->OSMemNFree = nblks; pmem->OSMemNBlks = nblks; pmem->OSMemBlkSize = blksize; OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return (pmem); (7) }

  7. Figure 12.4 The data structure after OSMemCreate() successful

  8. 12.02 Obtaining a Memory block, OSMemGet() • The APs need to understand how size of memory block is required • Need to provide the associated pointer of memory control block • When you are done using the block, you must return it to the proper memory partition void *OSMemGet (OS_MEM *pmem, INT8U *err) (1) { void *pblk; OS_ENTER_CRITICAL(); if (pmem->OSMemNFree > 0) { (2) pblk = pmem->OSMemFreeList; (3) pmem->OSMemFreeList = *(void **)pblk; (4) pmem->OSMemNFree--; (5) OS_EXIT_CRITICAL(); *err = OS_NO_ERR; return (pblk); (6) } else { OS_EXIT_CRITICAL(); *err = OS_MEM_NO_FREE_BLKS; return ((void *)0); } }

  9. Returning a Memory Block, OSMemPut() • If you return a wrong memory partition, the system may be crash or waste memory space INT8U OSMemPut (OS_MEM *pmem, void *pblk) (1) { OS_ENTER_CRITICAL(); if (pmem->OSMemNFree >= pmem->OSMemNBlks) { (2) OS_EXIT_CRITICAL(); return (OS_MEM_FULL); } *(void **)pblk = pmem->OSMemFreeList; (3) pmem->OSMemFreeList = pblk; pmem->OSMemNFree++; (4) OS_EXIT_CRITICAL(); return (OS_NO_ERR); }

  10. Obtaining Status of a Memory Partition, OSMemQuery() typedef struct { void *OSAddr; /* Points to beginning address of the memory partition */ void *OSFreeList; /* Points to beginning of the free list of memory blocks */ INT32U OSBlkSize; /* Size (in bytes) of each memory block */ INT32U OSNBlks; /* Total number of blocks in the partition */ INT32U OSNFree; /* Number of memory blocks free */ INT32U OSNUsed; /* Number of memory blocks used */ } OS_MEM_DATA; INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *pdata) { OS_ENTER_CRITICAL(); pdata->OSAddr = pmem->OSMemAddr; (1) pdata->OSFreeList = pmem->OSMemFreeList; pdata->OSBlkSize = pmem->OSMemBlkSize; pdata->OSNBlks = pmem->OSMemNBlks; pdata->OSNFree = pmem->OSMemNFree; OS_EXIT_CRITICAL(); pdata->OSNUsed = pdata->OSNBlks - pdata->OSNFree; (2) return (OS_NO_ERR); }

  11. Using Memory Partitions

  12. Scanning analog inputs and reporting errors AnalogInputTask() { for (;;) { for (all analog inputs to read) { Read analog input; (1) if (analog input exceed threshold) { Get memory block; (2) Get current system time (in clock ticks); (3) Store the following items in the memory block: (4) System time (i.e. a time stamp); The channel that exceeded the threshold; An error code; The severity of the error; Etc. Post the error message to error queue; (5) (A pointer to the memory block containing the data) } } Delay task until it’s time to sample analog inputs again; } } ErrorHandlerTask() { for (;;) { Wait for message from error queue; (6) (Gets a pointer to a memory block containing information about the error reported) Read the message and take action based on error reported; (7) Return the memory block to the memory partition; (8) } }

  13. Waiting for memory blocks from a partition OS_EVENT *SemaphorePtr; (1) OS_MEM *PartitionPtr; INT8U Partition[100][32]; OS_STK TaskStk[1000]; void main (void) { INT8U err; OSInit(); (2) . . SemaphorePtr = OSSemCreate(100); (3) PartitionPtr = OSMemCreate(Partition, 100, 32, &err); (4) . OSTaskCreate(Task, (void *)0, &TaskStk[999], &err); (5) . OSStart(); (6) } void Task (void *pdata) { INT8U err; INT8U *pblock; for (;;) { OSSemPend(SemaphorePtr, 0, &err); (7) pblock = OSMemGet(PartitionPtr, &err); (8) . . /* Use the memory block */ . OSMemPut(PartitionPtr, pblock); (9) OSSemPost(SemaphorePtr); (10) } }

More Related