Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2012 / uCOS / uCOSII_ebook.pdf
Скачиваний:
70
Добавлен:
10.02.2015
Размер:
1.08 Mб
Скачать

7.00 Memory Control Blocks

µC/OS-II keeps track of memory partitions through the use of a data structure called amemory control block as shown in listing 7.1. Each memory partition requires its own memory control block.

typedef struct {

void *OSMemAddr; void *OSMemFreeList; INT32U OSMemBlkSize; INT32U OSMemNBlks; INT32U OSMemNFree;

} OS_MEM;

Listing 7.1, Memory control block data structure.

OSMemAddr is a pointer to the beginning (i.e. base) of the memory partition from which memory blocks will be allocated from. This field is initialized when you create a partition (see section 7.01, Creating a partition) and is not used thereafter.

OSMemFreeListis a pointer used by µC/OS-II to point to either the next free memory control block or to the next free memory block. The use depends on whether the memory partition has been created or not (see section 7.01).

OSMemBlkSize determines the size of each memory block in the partition and is a parameter you specify when the memory partition is created (see section 7.01).

OSMemNBlks establishes the total number of memory blocks available from the partition. This parameter is specified when the partition is created (see section 7.01).

OSMemNFreeis used to determine how many memory blocks are available from the partition.

µC/OS-II initializes the memory manager if you configure OS_MEM_EN to 1 in OS_CFG.H. Initialization is done by OSMemInit() (which is automatically called by OSInit()) and consist of creating a linked list of

memory control blocks as shown in figure 7-3. You specify the maximum number of memory partitions with the configuration constant OS_MAX_MEM_PART (see OS_CFG.H) which MUST be set to at least 2.

As can be seen, t he OSMemFreeList field of the control block is used to chain the free control blocks.

OSMemAddr

 

OSMemAddr

 

OSMemAddr

OSMemFreeList OSMemFreeList OSMemFreeList OSMemFreeList 0

OSMemBlkSize

 

OSMemBlkSize

 

OSMemBlkSize

OSMemNBlks

OSMemNBlks

 

OSMemNBlks

 

 

 

 

 

OSMemNFree

OSMemNFree

 

OSMemNFree

OS_MAX_MEM_PART

Figure 7-3, List of free memory control blocks.

7.01 Creating a partition, OSMemCreate()

Your application must create each partition before they can be used. You create a memory partition by calling OSMemCreate(). Listing 7.2 shows how you could create a memory partition containing 100 blocks of 32 bytes each.

OS_MEM *CommTxBuf;

INT8U CommTxPart[100][32];

void main (void)

{

INT8U err;

OSInit();

.

.

CommTxBuf = OSMemCreate(CommTxPart, 100, 32, &err);

.

.

OSStart();

}

Listing 7.2, Creating a memory partition.

The code to create a memory partition is shown in listing 7.3. OSMemCreate() requires four arguments: the beginning address of the memory partition., the number of blocks to be allocated from this partition, the size (in bytes) of each block and, a pointer to a variable that will contain an error code when OSMemCreate() returns or a NULL pointer if OSMEMCreate() fails. Upon success, OSMemCreate() returns a pointer to the

allocated memory control block. This pointer must be used in subsequent calls to memory management services (see

OSMemGet(), OSMemPut() and OSMemQuery() in the next sections).

Each memory partition must contain at least 2 memory blocks L7.3(1). Also, each memory block must be able to hold

the size of a pointer because a pointer is used to chain all the memory blocks together L7.3(2). Next, OSMemCreate() obtains a memory control block from the list of free memory control blocks L7.3(3). The

memory control block will contain run-time information about the memory partition. OSMemCreate() will not

be able to create a memory partition unless a memory control block is available L7.3(4). If a memory control block is available and we satisfied all the previous conditions, the memory blocks within the partition are linked together in a

singly linked list L7.3(5). When all the blocks are linked, the memory control block is filled with information about the partition L7.3(6). OSMemCreate() returns the pointer to the memory control block so it can be used in

subsequent calls to access the memory blocks from this partition L7.3(7).

OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)

{

OS_MEM *pmem;

INT8U *pblk; void **plink;

INT32U i;

if (nblks < 2) {

 

(1)

*err = OS_MEM_INVALID_BLKS;

 

return ((OS_MEM *)0);

 

}

 

 

 

 

if (blksize < sizeof(void *)) {

(2)

*err = OS_MEM_INVALID_SIZE;

 

return ((OS_MEM *)0);

 

}

 

 

 

 

OS_ENTER_CRITICAL();

 

pmem = OSMemFreeList;

(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);

 

}

 

 

 

 

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)

}

Listing 7.3, OSMemCreate()

Figure 7-4 shows how the data structures look like when OSMemCreate() completes successfully. Note that

the memory blocks are sho w nicely linked one after the other. At run -time, as you allocate and de -allocate memory blocks, the blocks will most likely not be in this order.

pmem

 

 

OSMemAddr = addr

 

OSMemFreeList= addr

OSMemBlkSize = blksize

OSMemNBlks = nblks

OSMemNFree = nblks

Contiguous memory

OSMemCreate() arguments

0

Figure 7-4, OSMemCreate()

7.02 Obtaining a memory block, OSMemGet()

Your application can get a memory block from one of the created memory partition by calling OSMemGet(). You simply use the pointer returned by OSMemCreate() in the call to OSMemGet() to specify which partition the memory block will come from. Obviously, you application will need to know how big the memory block obtained is so that it doesn’t exceeds its storage capacity. In other words, you must not use more memory than what is available from the memory block. For example, if a partition contains 32 byte blocks then your application can use up to 32 bytes. When you are done using the block, you must return the block to the proper memory partition (see section 7.03,

Returning a memory block, OSMemPut()).

Listing 7.4 shows the code for OSMemGet(). The pointer specify the partition from which you want to get a memory block from L7.4(1). OSMemGet() first checks to see if there are free blocks available L7.4(2). If a block

is available, it is removed from the free list L7.4(3). The free list is then updated L7.4(4) so that it points to the next free memory block and, the number of blocks is decremented indicating that it has been allocated L7.4(5). The pointer to the allocated block is finally returned to your application L7.4(6).

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 {

 

 

Соседние файлы в папке uCOS