深入了解uCOSii是如何初始化内存控制块MCB和内存池的

为了便于说明uCOSii是如何初始化内存控制块MCB和内存池的,我将OS_MemInit()和OSMemCreate()两个函数从uCOSii中提取出来,单独测试。工作原理是一样的,我只是做一些简化工作,便于了解和学习。

1、测试程序如下:

#define InternalRAM_TotalNumberOfBytes  12  //定义内部堆区的大小为12字节
#define InternalRAM_BlockSize	           4  //每个存储块大小为4,必须为4的倍数
#define InternalRAM_NumberOfBlock 	InternalRAM_TotalNumberOfBytes/InternalRAM_BlockSize
//存储块的数量
//由于一个指针变量占用4字节,所以块的大小一定要为4的倍数
__align(4) uint8_t InternalRAM_Array[InternalRAM_NumberOfBlock][InternalRAM_BlockSize] __attribute__((at(0x20001000)));

typedef struct os_mem
{
	void   *OSMemAddr;   /*根节点地址*/
	void   *OSMemFreeList;/*下一个节点的地址*/
	uint32_t  OSMemBlkSize;/*节点的字节数*/
	uint32_t  OSMemNBlks; /*节点的总数量”*/
	uint32_t  OSMemNFree;/*可用节点数量*/
}OS_MEM;

__align(4) OS_MEM OSMemTbl[2] __attribute__((at(0x20001014)));//声明内存控制块
OS_MEM *OSMemFreeList;     //内存控制块指针
OS_MEM *InternalRAMPointer;//内存控制块指针
OS_MEM *InternalRAM2Pointer;//内存控制块指针

#define InternalRAM2_TotalNumberOfBytes  8  //定义内部堆区的大小为8字节
#define InternalRAM2_BlockSize	         4  //每个存储块大小为4,必须为4的倍数
#define InternalRAM2_NumberOfBlock 	InternalRAM2_TotalNumberOfBytes/InternalRAM2_BlockSize
//存储块的数量
//由于一个指针变量占用4字节,所以块的大小一定要为4的倍数
__align(4) uint8_t InternalRAM2_Array[InternalRAM2_NumberOfBlock][InternalRAM2_BlockSize] __attribute__((at(0x2000100C)));

//函数功能:对两个内存控制块进行初始化,OSMemFreeList指向"内存控制块0的首地址"
void OS_MemInit(void)
{
	int8_t *pdest;//声明pdest为"一维指针"
	int16_t size;
	OS_MEM  *pmem;//声明pmem为"OS_MEM型结构指针"
	int16_t current,next;

	pdest=(int8_t *)&OSMemTbl[0];//将"内存控制块0的首地址"保存到pdest
	size=sizeof(OSMemTbl);//求内存控制块OSMemTbl[]有多少个字节
	while(size>0)//将内存控制块清0
	{
		*pdest++ = (int8_t)0;
		size--;
	}

	for(current=0;current<1;current++)
	{
		pmem = &OSMemTbl[current];//将"内存控制块current的首地址"保存到pmem
		next=current+1;
		pmem->OSMemFreeList = (void *)&OSMemTbl[next];//将"内存控制块next的首地址"保存到pmem->OSMemFreeList
	}
	pmem= &OSMemTbl[current];
	//将"内存控制块current的首地址"保存到pmem
	//这里的OSMemTbl[current]是最后一个内存控制块
	pmem->OSMemFreeList=(void *)0;
	//由于"最后一个内存控制块"没有"下一个内存控制块"了,所有设置"下一个内存控制块的地址"为0

	OSMemFreeList=(OS_MEM *)&OSMemTbl[0];//将"内存控制块0的首地址"保存到OSMemFreeList
}

//addr为根节点地址
//nblks为节点的总数量
//blksize为节点的字节数
OS_MEM  *OSMemCreate (void *addr,uint32_t nblks,uint32_t blksize,uint8_t *perr)
{
	OS_MEM  *pmem;//声明pmem为"OS_MEM型结构指针"
	uint8_t *pblk;//声明pblk为"一维指针"
	void  **plink;//声明plink为"void型二维指针"
	uint32_t loops;
	uint32_t i;

	pmem = OSMemFreeList;//读取内存控制块指针
	if (OSMemFreeList != (OS_MEM *)0)
	{
		OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
		//将"下一个内存控制块的首地址"保存到OSMemFreeList,为初始化下一个内存池做准备
	}

	plink = (void **)addr;//将"void型一维指针addr"强制转换为"void型二维指针"保存到plink中
	pblk = (uint8_t *)addr;//将"void型一维指针addr"强制转换为"uint8_t型一维指针"保存到pblk中
	loops = nblks-1;//nblks为节点的总数量
	for(i=0;i<loops;i++)
	{
		pblk +=blksize;//将"下一个节点的首地"址保存到"uint8_t型一维指针pblk"
		*plink = (void  *)pblk;//将"uint8_t型一维指针pblk"强制转换为"void型一维指针"保存到"void型一维指针(*plink)"中
		plink = (void **)pblk;//将"uint8_t型一维指针pblk"强制转换为"void型二维指针"保存到"void型二维指针plink"中
	}
	*plink = (void *)0;
	//由于"最后一个节点"没有"下一个节点"了,所有设置"下一个节点的地址"为0

	pmem->OSMemAddr= addr;
	pmem->OSMemFreeList = addr;
	pmem->OSMemNFree= nblks;
	pmem->OSMemNBlks    = nblks;
	pmem->OSMemBlkSize  = blksize;
	return (pmem);
}

int main(void)
{
	uint8_t err;

	OS_MemInit();
	InternalRAMPointer=OSMemCreate(InternalRAM_Array,InternalRAM_NumberOfBlock,InternalRAM_BlockSize,&err);
	InternalRAM2Pointer=OSMemCreate(InternalRAM2_Array,InternalRAM2_NumberOfBlock,InternalRAM2_BlockSize,&err);
	
	GPIO_Config();
	while(1)
	{

		LED_ON();       //控制灯的引脚输出低电平;
		delay(360000);  //系统时钟为72MHz,延时为25ms;
		LED_OFF();      //控制灯的引脚输出高电平;
		delay(14400000); //系统时钟为72MHz,延时为1000ms;
	}
}

2、测试结果:

 

 

 编译器的显示更有说服力。

本程序对学习二维指针和数据类型强制转换,都是有帮助的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值