邝坚_北邮嵌入式实验报告_北邮嵌入式实验报告

2020-02-28 其他范文 下载本文

邝坚_北邮嵌入式实验报告由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“北邮嵌入式实验报告”。

嵌入式系统期末实验

一、实验要求

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

目的:在充分理解嵌入式处理器特点、RTOS 及强实时嵌入式系统软件设计规范的基础上,构建自己的实时系统软件框架基本功能,并在其上自拟应用(如部分模拟TCP 的C/S两端通信流程),测试软件框架的相关功能。

环境:VxWorks 的VxSim 仿真环境或2440(ARM920T)内容: 必选功能:

1.消息驱动的Task 统一框架,包含统一消息格式定义及使用规范; 2.支持消息驱动模式的软定时器的机制; 3.Task 启动同步功能;

4.体现前次实验中实现的自定义内存管理机制,最大限度降低外部碎片对系统可靠性的威胁。

可选功能(加分):

其它有利于实时处理的有效机制,如:无信号量(互斥)支持的临界资源访问方式,zero copy 等;

二、实现的功能

1.消息驱动的Task 统一框架,包含统一消息格式定义及使用规范; STATUS Task(){ Initialization(MBox, Data Structure, Timer, etc.)Forever{ MsgReceive If(…){ …… }else if(…){ …… } ……

} } typedef struct _MESSAGE { int mType;

/* 消息类型 0:timer->client *1:client->server 2:server->client*/ int mSendId;/* 发送任务的MESSAGE ID */ int mRecvId;/* 接收任务的MESSAGE ID */ int mData;/* 消息中传递的数据 */ }MESSAGE;2.支持消息驱动模式的软定时器的机制;

/* timer(id)向客户端消息队列定时发送的定时器*/ STATUS timer(int id){ MESSAGE* txMsg;/* 用于从消息队列中接收消息 */ int tick;/*创建一个定时,用于提醒发送者任务定时发送消息*/ 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%d send meage to tClient%d!n”,id,id);if(msgQSend(msgQIdClient[id],(char*)&txMsg,MAX_MSG_LEN,WAIT_FOREVER,MSG_{ return(ERROR);} PRI_NORMAL)== ERROR)

} } 3.Task 启动同步功能;

由manager()创建的任务优先级最高,先创建timer()、server()、client()的任务,让他们都在等待信号量semSynStart而被阻塞,最后创建manager()的任务,占据CPU,等待其他所有任务都被阻塞,解锁所有等待信号量的任务,让它们同时启动。/* progStart()启动实例程序*/ STATUS progStart(void){

int id;/* 用来区分不同的定时器或者客户任务 */ mallocPtr=&sysMalloc;mallocPtr->frontBlock = 0;return(OK);

initialPtr = initial();tidServer = tidManager = 0;for(id = 0;id

} /* 创建消息队列 */ msgQIdServer = msgQCreate(MAX_MSGS, MAX_MSG_LEN, MSG_Q_FIFO|MSG_Q_EVENTSEND_ERR_NOTIFY);if(msgQIdServer == NULL){

} for(id = 0;id

} 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

char tempName[20];sprintf(tempName, “tClient%d”, id);tidClient[id] = taskSpawn(tempName, 210, 0, STACK_SIZE, msgQIdClient[id] = msgQCreate(MAX_MSGS, MAX_MSG_LEN, if(msgQIdClient[id] == NULL){ return(ERROR);} MSG_Q_FIFO|MSG_Q_EVENTSEND_ERR_NOTIFY);return(ERROR);tidTimer[id] = 0;(FUNCPTR)client,id,0,0,0,0,0,0,0,0,0);} for(id = 0;id

} tidManager = taskSpawn(“tMannager”, 200, 0, STACK_SIZE,(FUNCPTR)manager,0,0,0,0,0,0,0,0,0,0);printf(“programe start!n”);return(OK);} /* manager()管理进程,实现task同步*/ STATUS manager(){ int id;while(taskIsSuspended(tidServer)|| taskIsReady(tidServer))

{ while(taskIsSuspended(tidClient[id])|| taskDelay(10);taskIsReady(tidClient[id]))

} for(id = 0;id

} semFlush(semSynStart);return(OK);} /* server()处理来自各个客户任务的消息*/ STATUS server(void){ …… while(taskIsSuspended(tidTimer[id])|| taskIsReady(tidTimer[id]))taskDelay(10);taskDelay(10);for(id = 0;id

semTake(semSynStart,WAIT_FOREVER);FOREVER { } /*client(id)向服务器任务发请求消息*/ STATUS client(int id){ ……

semTake(semSynStart,WAIT_FOREVER);FOREVER { } return(OK);} 4.体现前次实验中实现的自定义内存管理机制,最大限度降低外部碎片对系统可靠性的威胁。

静态内存的数据结构为单链表,采用头插法,申请内存时,修改firstavailable另其指向第二块,将firstavailable指向的头块取出,回收内存时,将回收的块的frontBlock指向第一块,修改firstavailable另其指向回收的块,将回收的块作为第一块,数据结构如下所示: …… ……

} return(OK);…… poolpoolHeadnextfirstavailable blockHeadfrontBlockblockHeadfrontBlockblockHeadfrontBlockblockHeadpoolHeadfirstavailableblockHeadfrontBlockblockHeadfrontBlockblockHeadfrontBlockblockHead 静态分配了含有32个16B块的内存池和含有16个256B块的内存池,如果申请的内存大于256B,调用系统malloc。

/*initial()初始化内存池*/ pool* initial(void){ int i;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指向申请内存区尾*/

/*初始化pool 1 该内存池分配大小为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

址*/ } /*初始化pool 2 该内存池分配大小为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

} return(pool*)mem;} blockHeadPtr=(blockHead*)((char*)blockHeadPtr + blockHeadPtr->poolId = 2;/* pool号为2,表示他是256B容量的*/ blockHeadPtr->frontBlock = poolHeadPtr->firstavailable;poolHeadPtr->firstavailable = blockHeadPtr;(sizeof(blockHead)+256));

blockHeadPtr=(blockHead*)((char*)blockHeadPtr + blockHeadPtr->poolId = 1;/* pool号为1,表示他是16B容量的*/ blockHeadPtr->frontBlock = poolHeadPtr->firstavailable;/* 当前首poolHeadPtr->firstavailable = blockHeadPtr;/* 求下一首个可用块地(sizeof(blockHead)+16));/*块的首址移动16加结构体的开销长度*/ 个可用块地址赋给frontBlock */

/*memMalloc()分配内存*/ void* memMalloc(int Size){ void* mem;poolHead* poolHeadPtr;blockHead* blockHeadPtr;

semTake(semMalloc,WAIT_FOREVER);

poolHeadPtr = initialPtr->pool;

if((Size available!= 0))/*长度小于16时,分配长度为16的内存空间*/ {

blockHeadPtr = poolHeadPtr->firstavailable;/*首个可用块地址赋给poolHeadPtr->firstavailable = blockHeadPtr->frontBlock;/*改变下poolHeadPtr->available--;/*可用块数减一*/ semGive(semMalloc);分配块的首地址*/ 一第一可用块的地址*/

return(void*)((char*)blockHeadPtr + sizeof(blockHead));/*分配内存时加入块头开销*/ } else if((Size next)->available!= 0))

{

} else

{ printf(“n[Warning] : Too large for blocks or the blocks are /*其他情况用系统的内存分配函数malloc分配*/ blockHeadPtr =(poolHeadPtr->next)->firstavailable;(poolHeadPtr->next)->firstavailable = blockHeadPtr->frontBlock;(poolHeadPtr->next)->available--;semGive(semMalloc);return(void*)((char*)blockHeadPtr + sizeof(blockHead));/*长度大于16小于256时,分配长度为256的内存空间*/ exhausted n”);

} } /*memFree()释放内存空间*/ void memFree(void* dataPtr){ char* mem=(char*)dataPtr;poolHead* poolHeadPtr;blockHead* blockHeadPtr;

semTake(semFree,WAIT_FOREVER);

poolHeadPtr = initialPtr->pool;/*恢复内存池首址*/ blockHeadPtr =(blockHead*)((char*)memsizeof(blockHead));Timer0Timer1Timer9ClientMsgQ0ClientMsgQ1……ClientMsgQ9Client0Client1Client9ServerMsgQserver6.zero copy 消息队列存储的是指向消息的指针,从而实现了零拷贝。#define MAX_MSG_LEN sizeof(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结束。

四、心得

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

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

《邝坚_北邮嵌入式实验报告.docx》
将本文的Word文档下载,方便收藏和打印
推荐度:
邝坚_北邮嵌入式实验报告
点击下载文档
相关专题 北邮嵌入式实验报告 实验报告 嵌入式 北邮 北邮嵌入式实验报告 实验报告 嵌入式 北邮
[其他范文]相关推荐
    [其他范文]热门文章
      下载全文