邝坚北邮嵌入式实验报告.docx

上传人:b****1 文档编号:14534323 上传时间:2023-06-24 格式:DOCX 页数:17 大小:133KB
下载 相关 举报
邝坚北邮嵌入式实验报告.docx_第1页
第1页 / 共17页
邝坚北邮嵌入式实验报告.docx_第2页
第2页 / 共17页
邝坚北邮嵌入式实验报告.docx_第3页
第3页 / 共17页
邝坚北邮嵌入式实验报告.docx_第4页
第4页 / 共17页
邝坚北邮嵌入式实验报告.docx_第5页
第5页 / 共17页
邝坚北邮嵌入式实验报告.docx_第6页
第6页 / 共17页
邝坚北邮嵌入式实验报告.docx_第7页
第7页 / 共17页
邝坚北邮嵌入式实验报告.docx_第8页
第8页 / 共17页
邝坚北邮嵌入式实验报告.docx_第9页
第9页 / 共17页
邝坚北邮嵌入式实验报告.docx_第10页
第10页 / 共17页
邝坚北邮嵌入式实验报告.docx_第11页
第11页 / 共17页
邝坚北邮嵌入式实验报告.docx_第12页
第12页 / 共17页
邝坚北邮嵌入式实验报告.docx_第13页
第13页 / 共17页
邝坚北邮嵌入式实验报告.docx_第14页
第14页 / 共17页
邝坚北邮嵌入式实验报告.docx_第15页
第15页 / 共17页
邝坚北邮嵌入式实验报告.docx_第16页
第16页 / 共17页
邝坚北邮嵌入式实验报告.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

邝坚北邮嵌入式实验报告.docx

《邝坚北邮嵌入式实验报告.docx》由会员分享,可在线阅读,更多相关《邝坚北邮嵌入式实验报告.docx(17页珍藏版)》请在冰点文库上搜索。

邝坚北邮嵌入式实验报告.docx

邝坚北邮嵌入式实验报告

 

嵌入式系统期末实验

 

一、实验要求

题目:

支持消息驱动模式的实时软件框架

目的:

在充分理解嵌入式处理器特点、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结束。

四、心得

实验中遇到了各种各样的问题,特别是代码调试,对报错的分析,定位错误,但是通过不懈努力,完成了本次实验,让我对课堂上所讲的内容有了更深刻的认识,对嵌入式实时操作系统有了更深的理解。

由于正值期末,考试任务繁重,时间紧迫,自身水平有限,难免会有疏漏,请老师指正。

[文档可能无法思考全面,请浏览后下载,另外祝您生活愉快,工作顺利,万事如意!

]

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2