邝坚北邮嵌入式实验报告.docx
- 文档编号:11398675
- 上传时间:2023-05-31
- 格式:DOCX
- 页数:17
- 大小:133.48KB
邝坚北邮嵌入式实验报告.docx
《邝坚北邮嵌入式实验报告.docx》由会员分享,可在线阅读,更多相关《邝坚北邮嵌入式实验报告.docx(17页珍藏版)》请在冰点文库上搜索。
邝坚北邮嵌入式实验报告
嵌入式系统期末实验
一、实验要求
题目:
支持消息驱动模式的实时软件框架
目的:
在充分理解嵌入式处理器特点、RTOS及强实时嵌入式系统软件设计规范的基础上,构建自己的实时系统软件框架基本功能,并在其上自拟应用(如部分模拟TCP的C/S两端通信流程),测试软件框架的相关功能。
环境:
VxWorks的VxSim仿真环境或2440(ARM920T)
内容:
必选功能:
1.消息驱动的Task统一框架,包含统一消息格式定义及使用规范;
2.支持消息驱动模式的软定时器的机制;
3.Task启动同步功能;
4.体现前次实验中实现的自定义内存管理机制,最大限度降低外部碎片对系统可靠性的威胁。
可选功能(加分):
其它有利于实时处理的有效机制,如:
无信号量(互斥)支持的临界资源访问方式,zerocopy等;
二、实现的功能
1.消息驱动的Task统一框架,包含统一消息格式定义及使用规范;
STATUSTask()
{
Initialization(MBox,DataStructure,Timer,etc.)
Forever{
MsgReceive
If(…)
{
……
}elseif(…)
{
……
}
……
}
}
typedefstruct_MESSAGE
{
intmType;/*消息类型0:
timer->client
*1:
client->server2:
server->client*/
intmSendId;/*发送任务的MESSAGEID*/
intmRecvId;/*接收任务的MESSAGEID*/
intmData;/*消息中传递的数据*/
}MESSAGE;
2.支持消息驱动模式的软定时器的机制;
/*timer(id)向客户端消息队列定时发送的定时器*/
STATUStimer(intid)
{
MESSAGE*txMsg;/*用于从消息队列中接收消息*/
inttick;/*创建一个定时,用于提醒发送者任务定时发送消息*/
tick=sysClkRateGet();
semTake(semSynStart,WAIT_FOREVER);
FOREVER
{
taskDelay((int)(tick*DELAY_SECOND));
txMsg=(MESSAGE*)memMalloc(MAX_MSG_LEN);
txMsg->mType=0;
txMsg->mSendId=MID_TIMER(id);
txMsg->mRecvId=MID_CLIENT(id);
txMsg->mData=0;
printf("tTimer%dsendmessagetotClient%d!
\n",id,id);
if(msgQSend(msgQIdClient[id],(char*)&txMsg,MAX_MSG_LEN,WAIT_FOREVER,MSG_PRI_NORMAL)==ERROR)
{
return(ERROR);
}
}
return(OK);
}
3.Task启动同步功能;
由manager()创建的任务优先级最高,先创建timer()、server()、client()的任务,让他们都在等待信号量semSynStart而被阻塞,最后创建manager()的任务,占据CPU,等待其他所有任务都被阻塞,解锁所有等待信号量的任务,让它们同时启动。
/*progStart()启动实例程序*/
STATUSprogStart(void)
{
intid;/*用来区分不同的定时器或者客户任务*/
mallocPtr=&sysMalloc;
mallocPtr->frontBlock=0;
initialPtr=initial();
tidServer=tidManager=0;
for(id=0;id { tidClient[id]=0; } for(id=0;id { tidTimer[id]=0; } /*创建消息队列*/ msgQIdServer=msgQCreate(MAX_MSGS,MAX_MSG_LEN,MSG_Q_FIFO|MSG_Q_EVENTSEND_ERR_NOTIFY); if(msgQIdServer==NULL) { return(ERROR); } for(id=0;id { msgQIdClient[id]=msgQCreate(MAX_MSGS,MAX_MSG_LEN,MSG_Q_FIFO|MSG_Q_EVENTSEND_ERR_NOTIFY); if(msgQIdClient[id]==NULL) { return(ERROR); } } semSynStart=semBCreate(SEM_Q_FIFO|SEM_EVENTSEND_ERR_NOTIFY,SEM_EMPTY); semMalloc=semBCreate(SEM_Q_PRIORITY,SEM_FULL); semFree=semBCreate(SEM_Q_PRIORITY,SEM_FULL); /*创建任务*/ tidServer=taskSpawn("tServer",220,0,STACK_SIZE,(FUNCPTR)server,0,0,0,0,0,0,0,0,0,0); for(id=0;id { chartempName[20]; sprintf(tempName,"tClient%d",id); tidClient[id]=taskSpawn(tempName,210,0,STACK_SIZE,(FUNCPTR)client,id,0,0,0,0,0,0,0,0,0); } for(id=0;id { chartempName[20]; sprintf(tempName,"tTimer%d",id); tidTimer[id]=taskSpawn(tempName,230,0,STACK_SIZE,(FUNCPTR)timer,id,0,0,0,0,0,0,0,0,0); } tidManager=taskSpawn("tMannager",200,0,STACK_SIZE,(FUNCPTR)manager,0,0,0,0,0,0,0,0,0,0); printf("programestart! \n"); return(OK); } /*manager()管理进程,实现task同步*/ STATUSmanager() { intid; while(taskIsSuspended(tidServer)||taskIsReady(tidServer)) taskDelay(10); for(id=0;id { while(taskIsSuspended(tidClient[id])||taskIsReady(tidClient[id])) taskDelay(10); } for(id=0;id { while(taskIsSuspended(tidTimer[id])||taskIsReady(tidTimer[id])) taskDelay(10); } semFlush(semSynStart); return(OK); } /*server()处理来自各个客户任务的消息*/ STATUSserver(void) { …… semTake(semSynStart,WAIT_FOREVER); FOREVER { …… } return(OK); } /*timer(id)向客户端定时发送的定时器*/ STATUStimer(intid) { …… semTake(semSynStart,WAIT_FOREVER); FOREVER { …… } return(OK); } /*client(id)向服务器任务发请求消息*/ STATUSclient(intid) { …… semTake(semSynStart,WAIT_FOREVER); FOREVER { …… } return(OK); } 4.体现前次实验中实现的自定义内存管理机制,最大限度降低外部碎片对系统可靠性的威胁。 静态内存的数据结构为单链表,采用头插法,申请内存时,修改firstavailable另其指向第二块,将firstavailable指向的头块取出,回收内存时,将回收的块的frontBlock指向第一块,修改firstavailable另其指向回收的块,将回收的块作为第一块,数据结构如下所示: 静态分配了含有32个16B块的内存池和含有16个256B块的内存池,如果申请的内存大于256B,调用系统malloc。 /*initial()初始化内存池*/ pool*initial(void) { inti; pool*mem; pool*poolPtr; poolHead*poolHeadPtr; blockHead*blockHeadPtr; mem=(pool*)malloc(6000);/*分配6000B内存作为内存池*/ /*初始化pool*/ poolPtr=(pool*)mem; poolPtr->poolNum=2; poolPtr->pool=(poolHead*)((char*)mem+sizeof(pool));/*pool指向申请内存区尾*/ /*初始化pool1该内存池分配大小为16B的内存*/ poolHeadPtr=(poolHead*)((char*)mem+sizeof(pool));/*初始化内存池的首地址*/ poolHeadPtr->available=32;/*初始化可用块数32*/ poolHeadPtr->blockSize=16;/*块大小16B*/ blockHeadPtr=(blockHead*)((char*)poolHeadPtr+sizeof(poolHead));/*初始化块的首地址*/ poolHeadPtr->firstavailable=blockHeadPtr;/*初始化第一块可用块的地址*/ poolHeadPtr->next=(poolHead*)((char*)poolHeadPtr+sizeof(poolHeadPtr)+32*(sizeof(blockHead)+16));/*next指向第二个内存池*/ blockHeadPtr->poolId=1; blockHeadPtr->frontBlock=0; for(i=1;i<32;i++)/*将该内存池划分为32个容量16B的内存块*/ { blockHeadPtr=(blockHead*)((char*)blockHeadPtr+(sizeof(blockHead)+16));/*块的首址移动16加结构体的开销长度*/ blockHeadPtr->poolId=1;/*pool号为1,表示他是16B容量的*/ blockHeadPtr->frontBlock=poolHeadPtr->firstavailable;/*当前首个可用块地址赋给frontBlock*/ poolHeadPtr->firstavailable=blockHeadPtr;/*求下一首个可用块地址*/ } /*初始化pool2该内存池分配大小为256B的内存*/ poolHeadPtr=poolHeadPtr->next; poolHeadPtr->available=16;/*初始化可用块数16*/ poolHeadPtr->blockSize=256;/*块大小256*/ blockHeadPtr=(blockHead*)((char*)poolHeadPtr+sizeof(poolHead)); poolHeadPtr->firstavailable=blockHeadPtr; poolHeadPtr->next=0; blockHeadPtr->poolId=2; blockHeadPtr->frontBlock=0; for(i=1;i<16;i++)/*将该内存池划分为16个容量256B的内存块*/ { blockHeadPtr=(blockHead*)((char*)blockHeadPtr+(sizeof(blockHead)+256)); blockHeadPtr->poolId=2;/*pool号为2,表示他是256B容量的*/ blockHeadPtr->frontBlock=poolHeadPtr->firstavailable; poolHeadPtr->firstavailable=blockHeadPtr; } return(pool*)mem; } /*memMalloc()分配内存*/ void*memMalloc(intSize) { void*mem; poolHead*poolHeadPtr; blockHead*blockHeadPtr; semTake(semMalloc,WAIT_FOREVER); poolHeadPtr=initialPtr->pool; if((Size<=16)&&(poolHeadPtr->available! =0))/*长度小于16时,分配长度为16的内存空间*/ { blockHeadPtr=poolHeadPtr->firstavailable;/*首个可用块地址赋给分配块的首地址*/ poolHeadPtr->firstavailable=blockHeadPtr->frontBlock;/*改变下一第一可用块的地址*/ poolHeadPtr->available--;/*可用块数减一*/ semGive(semMalloc); return(void*)((char*)blockHeadPtr+sizeof(blockHead));/*分配内存时加入块头开销*/ } elseif((Size<=256)&&((poolHeadPtr->next)->available! =0)) /*长度大于16小于256时,分配长度为256的内存空间*/ { blockHeadPtr=(poolHeadPtr->next)->firstavailable; (poolHeadPtr->next)->firstavailable=blockHeadPtr->frontBlock; (poolHeadPtr->next)->available--; semGive(semMalloc); return(void*)((char*)blockHeadPtr+sizeof(blockHead)); } else/*其他情况用系统的内存分配函数malloc分配*/ { printf("\n[Warning]: Toolargeforblocksortheblocksareexhausted\n"); mem=malloc(Size);/*采用系统函数malloc()分配内存*/ blockHeadPtr=(blockHead*)mem; blockHeadPtr->poolId=(initialPtr->poolNum+1); blockHeadPtr->frontBlock=mallocPtr; mallocPtr=blockHeadPtr; semGive(semMalloc); return(void*)((char*)blockHeadPtr+sizeof(blockHead)); } } /*memFree()释放内存空间*/ voidmemFree(void*dataPtr) { char*mem=(char*)dataPtr; poolHead*poolHeadPtr; blockHead*blockHeadPtr; semTake(semFree,WAIT_FOREVER); poolHeadPtr=initialPtr->pool;/*恢复内存池首址*/ blockHeadPtr=(blockHead*)((char*)mem-sizeof(blockHead));/*恢复内存块首址*/ if(blockHeadPtr->poolId==1)/*释放16B的内存块*/ { blockHeadPtr->frontBlock=poolHeadPtr->firstavailable;/*恢复frontBlock地址*/ poolHeadPtr->firstavailable=blockHeadPtr;/*恢复第一可用块地址*/ poolHeadPtr->available++;/*恢复可用块数*/ } elseif(blockHeadPtr->poolId==2)/*释放256B的内存块*/ { blockHeadPtr->frontBlock=(poolHeadPtr->next)->firstavailable; (poolHeadPtr->next)->firstavailable=blockHeadPtr; (poolHeadPtr->next)->available++; } else/*释放由系统分配的内存块*/ { blockHeadPtr=mallocPtr; mallocPtr=blockHeadPtr->frontBlock; free((char*)mem-sizeof(blockHead)); } semGive(semFree); return; } /*memDel()删除内存块*/ voidmemDel(void) { void*mem; blockHead*blockHeadPtr; mem=(void*)(initialPtr); free(mem); while(mallocPtr->frontBlock! =0) { mem=(void*)(mallocPtr); free(mem); mallocPtr=mallocPtr->frontBlock; } semDelete(semMalloc);/*删除信号量*/ semDelete(semFree); } 5.无信号量(互斥)支持的临界资源访问方式 有一个server任务,有10个client任务,10个client任务定时给server的消息队列发送消息,server任务接收到消息后,发送ACK消息到client的消息队列,如图: 6.zerocopy 消息队列存储的是指向消息的指针,从而实现了零拷贝。 #defineMAX_MSG_LENsizeof(MESSAGE*) MESSAGE*rxMsg;/*用于从消息队列中接收消息*/ MESSAGE*txMsg;/*用于向消息队列中发送消息*/ msgQReceive(msgQIdServer,(char*)&rxMsg,MAX_MSG_LEN,WAIT_FOREVER); msgQSend(msgQIdClient[mSendId],(char*)&txMsg,MAX_MSG_LEN,WAIT_FOREVER,MSG_PRI_NORMAL); 三、运行结果 在shell中输入progStart,观察VxSim,输入progStop结束。 四、心得 实验中遇到了各种各样的问题,特别是代码调试,对报错的分析,定位错误,但是通过不懈努力,完成了本次实验,让我对课堂上所讲的内容有了更深刻的认识,对嵌入式实时操作系统有了更深的理解。 由于正值期末,考试任务繁重,时间紧迫,自身水平有限,难免会有疏漏,请老师指正。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 邝坚北邮 嵌入式 实验 报告