Memory and queue management under embedded no operating system (like UCOS II thought)

Example: Store logs, with a maximum of 128 entries, each with a maximum of 1MB.

Memory aspect Because embedded is not suitable for dynamic memory, fragmentation will occur. Here we use u8 data[LOG_SIZE]; to open up a fixed 128MB memory area, and then divide it into 128 1MB memory blocks for management.
The management method is: use a memory control block structure MCB, and then write addition, deletion and modification functions to operate the MCB for management.

In terms of queues, we use circular queues. For example, the queue has up to 10 elements. When we store the 11th element, it will overwrite the first one.
The management method is: use a queue control block structure LoopQueue, and then write addition, deletion and modification functions to operate LoopQueue for management.

The association between the memory block and the queue is based on pointers:
such as ( memory block 1 where information is stored ) and ( queue position 1)
①We can store the address pointer of memory block 1 in queue position 1;
②You can also define a new structure The body contains the address pointer of memory block 1, the serial number of the message, and the time of the message. Then store the pointer of this structure into the queue position 1.

1. Manage 128MB memory

#define LOG_SIZE 0x8000000  //  (0x8000000 / 1024 / 1024= 128)
#define Blk_Num 128

//内存控制块结构体 Memory control block
typedef struct _MCB {
    
    
    void*   BeginAddr;  //指向开辟的内存的首地址
    uint32  TotalSize;  //开辟内存的总大小
    uint32  BlkSize;    //每个内存块的大小
    uint32  BlkNums;    //开辟的总内存块数目
    uint32  FreeBlks;   //可用的内存块数目
    uint32  BlkOut;     //获取内存时释放的位置
    uint32  BlkIn;      //回收内存时存放的位置
    uint32  MemAddr[Blk_Num];//该数组存储所有内存块的首地址
} MCB;

//对指定内存的实际操作就靠这两个全局变量
u8 data[LOG_SIZE];
MCB LogMCB;

//初始化,应该用函数执行,这里简单贴出来:
memset(data,0,sizeof(u8)*LOG_SIZE);

LogMCB.BeginAddr = data;
LogMCB.TotalSize = 0x8000000*sizeof(u8); //128MB
LogMCB.BlkSize   = 0x100000*sizeof(u8);  //1MB
LogMCB.BlkNums   = LogMCB.TotalSize/LogMCB.BlkSize;
LogMCB.FreeBlks  = LogMCB.BlkNums;
LogMCB.BlkIn     = 0;
LogMCB.BlkOut    = 0;
For(i=0;i<LogMCB.BlkNums;i++)
{
    
    
    LogMCB.MemAddr[i] = LogMCB.BeginAddr+(i*LogMCB.BlkSize);
}

//获取一块内存时各变量对应的操作:
LogMCB.MemAddr[LogMemObj.BlkOut] = 0; 置零
LogMCB.BeginAddr;   不变
LogMCB.TotalSize;   不变
LogMCB.BlkSize;     不变
LogMCB.BlkNums;     不变
LogMCB.FreeBlks--;  减一
LogMCB.BlkOut++;    加一
LogMCB.BlkIn;       不变

//释放一块内存时各变量对应的操作:
LogMCB.MemAddr[LogMemObj.BlkIn]  = addr;  赋值
LogMCB.BeginAddr;   不变
LogMCB.TotalSize;   不变
LogMCB.BlkSize;     不变
LogMCB.BlkNums;     不变
LogMCB.FreeBlks++;  加一
LogMCB.BlkOut;      不变
LogMCB.BlkIn++;     加一


The code is functional analysis. In actual use, initialize memory, acquire memory, and release memory should be packaged as functions.

Insert picture description here
//To understand the meaning and usage of each member of the memory control structure
typedef struct _MCB { void* BeginAddr; //Point to the first address of the opened memory uint32 TotalSize; //Total size of the opened memory uint32 BlkSize; //Each memory The size of the block uint32 BlkNums; //Total number of memory blocks opened uint32 FreeBlks; //The number of available memory blocks uint32 BlkOut; //The location released when the memory is acquired uint32 BlkIn; //The location where the memory is stored uint32 MemAddr[Blk_Num ];//This array stores the first address of all memory blocks } MCB;








//The actual operation of the specified memory depends on these two global variables
u8 data[LOG_SIZE];
MCB LogMCB;

Second, with a circular queue management log
if the log is we have to send and receive operations, the actual queue may only 50, will be able to meet the transceiver 128 of the log. Therefore, the number of queues does not have to be as large as the number of memory blocks.

#define MAX 128
typedef struct _LoopQueue 
{
    
    
    uint32    QueueMax;     //队列最大数目
    uint32    QueueUsed;    //使用了的数目
    uint32    QueueIn;      //进队位置
    uint32    QueueOut;     //出队位置
    void      *Member[MAX]; //存储每条日志的结构体指针
} LoopQueue;

LoopQueue LogQueue;

//initial
LogQueue.QueueMax  = MAX;
LogQueue.QueueUsed = 0;
LogQueue.QueueIn   = 0;
LogQueue.QueueOut  = 0;
for(int i=0;i<MAX;i++)
{
    
    
    LogQueue.Member[i] = NULL;
}

//存储一条日志到内存块后,将内存块地址存入队列。我们发送日志时 直接操作队列、间接操作内存块:
void *nowlog = LogMCB.MemAddr[LogMemObj.BlkOut] ;
LogMCB.MemAddr[LogMCB.FreeRingOut]  = 0;
LogMCB.FreeBlks--;  
LogMCB.BlkOut++;    

LogQueue.Member[LogQueue.QueueIn]  =  (void *)nowlog ;
LogQueue.QueueUsed ++;
LogQueue.QueueIn   ++;

//删除一条日志时:
LOG * nlog = (LOG *)LogQueue.Member[LogQueue.QueueOut]  ;
LogQueue.Member[LogQueue.QueueOut] = NULL;
LogQueue.QueueOut ++
LogQueue.QueueUsed --;

LogMCB.MemAddr[LogMCB.BlkIn]  = (void *)nlog;  
LogMCB.FreeBlks++;  
LogMCB.BlkIn++;     

//队列实现循环:
LogQueue.QueueIn  = LogQueue.QueueIn % LogQueue.QueueMax ;  //比如存第129条,会存储到物理第一条的位置
LogQueue.QueueOut = LogQueue.QueueOut  % LogQueue.QueueMax ; 

Insert picture description here
The more important ones are memory initialization, memory usage, memory recovery, queue initialization, queue usage, and queue recovery. In addition to the actual assignment of the log, pointers are used for interaction in many places.

Mainly to understand when storing and deleting logs: memory management and queue management:
//When storing a log:
//1, use a memory block
void* nowlog = LogMCB.MemAddr[LogMCB.BlkOut];
LogMCB.MemAddr[ LogMCB.FreeRingOut] = 0;
LogMCB.FreeBlks–;
LogMCB.BlkOut++;

//2. Write the log at the address (not necessarily using this method)
memcpy(nowlog ,pdata, 0x100000*sizeof(u8));

//3, store the log pointer in the queue
LogQueue.Member[LogQueue.QueueIn] = (void )nowlog;
LogQueue.QueueUsed ++;
LogQueue.QueueIn ++;

//When deleting a log:

//1, take out the log pointer in the queue
void
nowlog = (LOG *)LogQueue.Member[LogQueue.QueueOut];
LogQueue.Member[LogQueue.QueueOut] = NULL;
LogQueue.QueueOut ++;
LogQueue.QueueUsed --;
//2, the log pointer is also the pointer of the first address of the memory block, reclaim the memory block
LogMCB.MemAddr[LogMCB.BlkIn] = (void *)nlog;
LogMCB.FreeBlks++;
LogMCB.BlkIn++;

//Queue implementation loop:

LogQueue.QueueIn = LogQueue.QueueIn% LogQueue.QueueMax;
//For example, if you save the 129th item, it will be stored in the first physical location
LogQueue.QueueOut = LogQueue.QueueOut% LogQueue.QueueMax;

Guess you like

Origin blog.csdn.net/LIU944602965/article/details/103277573