




已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
UC/OS-II嵌入式系统在ARM上的移植UC/OS-II操作系统是一款完全公开的源代码,它非常精简,整个操作系统的代码只有几千行,是专门针对于嵌入式开发而产生的一款代码。它有几个特点,分别是可移植性(Portable)、可固化(ROMable)、可裁剪(Scalable)、多任务、可确定性、任务栈、系统服务、中断管理、稳定性可靠性。UC/OS-II主要就是一个内核,由ANSIC语言编写而成。负责任务管理和任务调度,没有文件系统和界面系统。它的代码是公开的,系统的实时性强、移植性好、可多任务。UC/OS-II作为基于优先级的抢占式多任务的实时操作系统,包含了实时内核、任务管理、时间管理、任务间通信同步和内存管理的功能。它使得任务的独立性,不相互干涉,非常的准时和高效,且易于设计和扩展。UO/OS-II共有16个内核文件,11个与CPU类型无关,就是说可以直接使用不需要修改。还有3个内核文件与CPU有关系,要根据需要作出相应的改动。剩下的两个内核文件和具体的应用有关。如图所示UC/OS-II的16个内核文件的层次。应用程序 与处理器类型无关的内核代码OSCORE.C OS_FLAG.COS_MBOX.C OS_MEN.COS_MUTEX.C OS_Q.COS_SEM.C OS_TASK.CC/OS-II.COS_TIME.C C/OS-II.C 与应用有关的内核配置文件OS_CFG.HINCLUDE.H与处理器类型有关的内核代码OS_CPU.H OS_CPU.ASM OS_CPU_C.CCPU定时器 软件硬件C/OS-II内核文件多任务操作的核心是系统调度器,利用TCB来管理任务调度功能。它的主要功能是保存任务的当前态、优先级、等待事件、代码起始地址、初始堆栈指针等。程序的设计关键就是确定划分多任务的问题,以及任务优先级和任务通信。优先级的意思是每个任务都是无限循环的,有运行态度、就绪态、休眠态、挂起态和中断五种状态。当有高一级优先级的任务就绪后,低优先级立即停止运行,转为挂起态或就绪态。这就是可剥夺型的内核。当中断一个高优先级任务,中断时挂起,中断结束后任务继续运行,并立即剥夺低优先级的任务。对于这种可剥夺型内核,CPU的使用时可以确定的,可优化任务级响应。在很多单片机或ARM板上很容易就可以移植UC/OS-II。当然本次设计使用的TQ2440,也可以完美的移植它。移植程序在网上都可以找得到,所以设计中就不做解释了。本次设计实现的是串口协议和网口协议组合成的一个数据网关。其主要的流程图如下所示:以太网现场数据网RJ45接口IP分组封帧RS232接口封帧解帧解帧开始系统初始化OSInit()OS_InitMisc()混合变量初始化OS_InitRdyList()就绪表初始化OS_InitTCBList()任务控制块初始化OS_InitEventList()事件控制块初始化根据延时或消息调度运行OS_FlagInit()事件标志初始化OS_MemInit()内存管理OS_SemInit()消息初始化OS_InitTaskIdle()创建空闲任务定时器初始化串行口初始化创建任务TASK_UipRec 以太网接收 优先级:4TASK_UipTimeOut 定时任务 优先级:3TASK_UipProcess:uip协议处理 优先级: 2OSStart()启动调度开始运行UART中断DM9000外部中断断 如图所示可以很清楚的看出内核操作系统对于整个系统的控制过程,下面我们要介绍一下UC/OS-II里面的一些程序。用户应用程序任务定义代码如下:void MyTask( void *pdata) /开始定义用户任务 for(;) . void main()TargetInit(); /完成初始化目标开发板。OSInit (); /完成初始化UCOS-II。OSTimeSet(0); /完成初始化系统时基。OSTaskCreate (MainTask,(void *)0, &MainTaskStkMainTaskStkLengh - 1, MainTaskPrio); /开始创建系统初始任务。OSStart (); /整个任务开始。return 0;void Task0(void *pdata) /主任务建立:taks0 和 task1#if OS_CRITICAL_METHOD = 3/* 分配CPU状态寄存器*/OS_CPU_SR cpu_sr;#endifOS_ENTER_CRITICAL();Timer0Init();/初始化报时信号ISRInit(); /初始化中断优先级 OS_EXIT_CRITICAL();OSPrintfInit();/用户任务给串口 DM9000_init();OSStatInit(); while(1)OSPrintf(nEnter Main Taskn);/测试Dm9000/打印DM9000寄存器OSTimeDly(OS_TICKS_PER_SEC);需要注意的是,C/OS-II的应用程序要使用空闲任务OSTaskldle(),而它是不可删除的系统文件。下面开始对应用程序进行移植了。本次设计是在ARM开发板上实现串口、网口数据转换的的功能。在TQ2440上有串口和网口。通信过程简单的描述就是PC串口发送数据给ARM板,ARM接到串口数据后,从网口再传给PC。相反也是同样的道理,由网口发送数据,有ARM控制由串口发回数据。首先是TCP/IP协议的移植。在编写移植程序前,有必要解释一下基本的协议栈作用和意义。就常见的网络通信方式一般来说有两种:1、UART-RS232,此时只需要pc上有串口调试助手即可。2、TCP/IP,这时候和普通pc与pc通信一样 可以用socket套接字编程也可用别人写好的软件侦听。而现在我们要实现的是串口控制单片机与PC机的通信,在这里用PC来代替以太网。接下来还要介绍一下以太网接口。以太网技术如今已经相当的成熟了,其相应的网络产品价格低廉、技术完善。而数据总线如今越来越难以满足人们日益提升的需要,这时以太网控制网络技术得到了快速的发展,并形成了现场总线的新标准。加上国内大部分局域网是以太网,给予以太网实现现场总线有了雄厚的物质基础。以太网的接口就是以太网同信的基础,是通信介质通信的中间处理部件,实现报文的发送与接收功能,位于TCP/IP协议栈的数据链路层。每一个以太网接口(有时候也叫网卡),在连通后就可以随时的发送和接收网络上的数据,执行EEE802.3标准。TCP/IP对应的ISO结构如图所示:应用层数据链路层会话层传输层网络层应用层物理层网络接口层 传输层 网络层表示层 TCP/IP协议栈而单片机与计算机的TCP/IP协议的实现也有很大的不同,原本在计算机里编写的程序可以不考虑代码的大小和效率,但在嵌入式开发板上都要考虑到这些问题。在操作系统、内存分配、指针、参数传递、协议支持以及硬件接口的设计方面有些不同。首先就是操系统,嵌入式的特点之一就是简洁高效,有很强的专业功能。相对而言计算机上的操作系统的侧重点就是兼容性,所以资源要求全面支持,所以很复杂。其次就是内存上的分配,计算机像windows系统它的内存分配是动态的,而在单片机上却不能同样如此,应为RAM的容量所限,所以其中存放以太网的数据包是固态的。由于ARM相对于单片机的能力而言有了很大的提升,所以可以突破单片机的一些约束。如下图所示,TCP/IP协议栈中的内容,从上往下分别对应应用层、传输层、网络层和网络接口层。用户进程用户进程用户进程TCPUDPICMPIPARP硬件接口 TCP/IP协议栈在本次设计中采用Lwip协议栈来实现ARM与以太网的连接。完成移植后,需要介绍一下以太网的初始化过程和数据收发过程。LWIP的初始化要在UC/OS-II之后,在其它任务创建之前。因为LWIP要对以太网协议栈初始化以及新线程的建立,LWIP初始化如图所示。LwIP_Init()Sys_mbox_new()Low_level _Init()Tcpip_Init()EMACInit()Low_level_output()netif-linkoutputlwip_init()Ethernetif_Init()netif-outputSys_thread_new () 以太网初始化流程(1)(3)(4)(8)(2)(7)(9)(5)(6)(10)(11)etharp_output ()netif-inputtcpip_input ()(12)(13)(14)指向指向指向LWIP程序可以实现很多功能,在本设计中没有实现他的全部功能。而简单的PING通需要DM9000来实现。以太网的接收是通过中断方式,如果有数据进入以太网中断函数。其主要任务就是读取和分析数据包。如果数据有效则在Tcpip_input()函数把数据发送出去,并在LWIP初始化创建的线程中就可以得到此消息。然后通过ip_input()函数进入传输层后,再把把数据传到应用层。具体流程如下图所示:Mbox方式传递数据,tcpip_thread()消息识别分类通过网络接口函数netif-output直接指向netconn_write ()tcp_write ()tcp_enqueuet()tcp_output ()应用层TCPIP_APIMSG ()tcpip_apimsg()do_write ()以太网数据发送流程etharp_output ()etharp_send_ip ()ETH_TxPkt_ChainMode ()low_level_output ()ip_output ()ip_output_if ()通过网络接口函数netif-linkoutput直接指向ETH_IRQHandlert()Ethernetif_input()以太网数据接收流程Tcpip_input()Low_level_input()ethernet_input()EMACReadPacket ()GetInputPacketLen()tcp_input ()tcp_process ()ip_input ()update_arp_entry ()etharp_ip_input ()tcp_receive ()TCP_EVENT_RECV ()recv_tcp ()netconn_recv ()应用层Mbox方式传递数据,在tcpip_thread()中消息识别分类Recv_mbox方式进行数据传递通过网络接口函数netif-intput直接指向为什么要选择DM9000网络驱动器呢?如今嵌入式中大量使用10/100M的以太网卡,实际上并不实用。因为它不能既满足快速传输速率又满足成本控制。这时,DM9000作为一种综合低成本的单一快速以太网控制芯片就有了很高的实用价值。它具有通用的接口,设计简单,可满足不同系统的软件驱动。DM9000程序的体系结构可以分为网络协议接口、设备接口层、功能层及媒介层。下面是DM9000的部分驱动程序的编写。定义DM9000:#include config.h#define DM_ADD (*(volatile unsigned short *) 0x20000300)#define DM_CMD (*(volatile unsigned short *) 0x20000304)#define Printf OSPrintfuint8 Buffer1000;/定义了一个1000字节的接收发送缓冲区uint8 host_mac_addr6= 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ; /主机的MAC地址uint8 mac_addr6 = 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f ; /开发板 0a,1b,2c,3d,4e,5f ,这实际上是一个软地址,在本设计中不需要特指。uint8 ip_addr4 = 192, 168, 1, 6;uint8 host_ip_addr4 = 192, 168, 1, 100 ;uint16 packet_len;/接收、发送数据包的长度,单位为字节uint8 arpsendbuf60=0xff,0xff,0xff,0xff,0xff,0xff,/以太网目标地址0x0a,0x1b,0x2c,0x3d,0x4e,0x5f,/以太网源地址0x08,0x06,/帧类型:ARP帧0x00,0x01,/硬件类型:以太网0x08,0x00,/协议类型:IP协议0x06,/硬件地址长度:6字节0x04,/协议地址长度:4字节0x00,0x00,/操作: ARP请求0x0a,0x1b,0x2c,0x3d,0x4e,0x5f,/发送端硬件地址192, 168, 1, 6, /发送端协议地址0x00,0x00,0x00,0x00,0x00,0x00,/接收端硬件地址192, 168, 1, 100/接收端协议地址;#define DM9KS_ID0x90000A46#define DM9KS_VID_L0x28#define DM9KS_VID_H0x29#define DM9KS_PID_L0x2A#define DM9KS_PID_H0x2B#define DM9KS_BASE_ADDR_ETH00x20000000/nGCS4#define DM9KS_Index(*(volatile unsigned short *)(DM9KS_BASE_ADDR_ETH0 + 0x300)#define DM9KS_Data(*(volatile unsigned short *)(DM9KS_BASE_ADDR_ETH0 + 0x304)接下是来对DM9000进行初始化的程序部分:void DM9000_init(void)uint32 i;/Test_DM9000AE();IOSetInit(); /设置中断EINIT7/初始化设置步骤: 1dm9000_reg_write(DM9000_GPCR, 0x01);/设置GPCR(1EH) bit0=1,使DM9000的GPIO3为输出。dm9000_reg_write(DM9000_GPR, 0x00);/GPR bit0=0 使DM9000的GPIO3输出为低以激活内部PHY。udelay(5000);/延时2ms以上等待PHY上电。/初始化设置步骤: 2dm9000_reg_write(DM9000_NCR, 0x03);/软件复位udelay(3000);/延时20us以上等待软件复位完成dm9000_reg_write(DM9000_NCR, 0x00);/复位完成,设置正常工作模式。dm9000_reg_write(DM9000_NCR, 0x03);/第二次软件复位,为了确保软件复位完全成功。此步骤是必要的。udelay(3000);dm9000_reg_write(DM9000_NCR, 0x00); /以上完成了DM9000的复位操作/初始化设置步骤: 3dm9000_reg_write(DM9000_NSR, 0x2c);/清除各种状态标志位dm9000_reg_write(DM9000_ISR, 0xbf);/清除所有中断标志位/以上清除标志位/初始化设置步骤: 4 dm9000_reg_write(DM9000_RCR, 0x39);/接收控制 dm9000_reg_write(DM9000_TCR, 0x00);/发送控制 dm9000_reg_write(DM9000_BPTR, 0x3f); dm9000_reg_write(DM9000_FCTR, 0x38);/接收FIFO门限3k 8k dm9000_reg_write(DM9000_FCR, 0xff); dm9000_reg_write(DM9000_SMCR, 0x00); /以上是功能控制 /初始化设置步骤: 5for(i=0; i6; i+)dm9000_reg_write(DM9000_PAR + i, mac_addri);/mac_addr自己定义一下吧,6个字节的MAC地址/以上存储MAC地址(网卡物理地址)到芯片中去,这里没有用EEPROM,所以需要自己写进去/初始化设置步骤: 6dm9000_reg_write(DM9000_NSR, 0x2c);/清除各种状态标志位dm9000_reg_write(DM9000_ISR, 0x3f);/清除所有中断标志位/初始化设置步骤: 7dm9000_reg_write(DM9000_IMR, 0x81);/中断使能/中断使能(或者说中断屏蔽),即开启我们想要的中断,关闭不想要的,这里只开启的一个接收中断udelay(10000);/延时2ms以上等待PHY上电。 /PrintfDM9000Reg();Printf(DM9000初始化完毕rn);接下来是数据包的接收和发送流程图和程序:DM9000收到封包,置于接收内存的0C00h-3FFFh。若超过最大值时,会自动把位置移到0C0h0位置。每个封包有4字节是存放一些与封包相关的信息。若内存的第1字节值为“01h”,表明封包已经在内存中了。在读取其它字节前,先要确定第2个字节,则是这个封包的相关信息。如下图是DM9000接收封包流程:开始初始化MRCMDX=0x01?读前4个字节封包正确时ARP或IP包?剩下的数据返回1无新包接收错误返回0NNNYYY DM9000接收封包流程如图可以看出,DM9000从网络中接到一个数据包后,在数据包前面加了4个字节,分别为“01H”、“status”、“LENL”(包长的低8位)、“LENH”(包长的高8位)。这4个字节来确定数据包的状态,“01H”表示接下来的是有效数据包,“00H”则表示没有数据包,其它值则表示没有正确初始化,并重新初始化。若数据包长度小于60字节,则DM9000芯片会自动为不足的字节补上0。同时,在接收到的包后程序还会自动添加4个CRC校验字节。于是,接收到的数据包至少为64字节。也根据TCP/IP协议从首部字节中找出有效字节数,这就是TCP/IP协议栈的功能了。具体程序如下:/接受数据包/参数:datas为接收到是数据存储位置(以字节为单位)/返回值:接收成功返回数据包类型,不成功返回0uint32 receivepacket(uint8 *datas)uint16 i,tmp,status,len;uint8 ready;uint32 st;ready = 0;/希望读取到01Hstatus = 0;/数据包状态len = 0; /数据包长度 if(dm9000_reg_read(DM9000_ISR) & 0x01) dm9000_reg_write(DM9000_ISR, 0x01);/清除接收中断标志位 ready = dm9000_reg_read16(DM9000_MRCMDX); / 第一次读取,一般读取到的是 00HPrintf(ready1 = %xrn,ready); if(ready & 0x0ff) != 0x01) ready = dm9000_reg_read16(DM9000_MRCMDX); / 第二次读取,总能获取到数据 Printf(ready2 = %xrn,ready); if(ready & 0x01) != 0x01) if(ready & 0x01) != 0x00) /若第二次读取到的不是01H或00H ,则表示没有初始化成功 dm9000_reg_write(DM9000_IMR, 0x80);/屏蔽网卡中断 DM9000_init(); /重新初始化 dm9000_reg_write(DM9000_IMR, 0x81);/打开网卡中断 return 0; / status = dm9000_reg_read16(DM9000_MRCMD); DM_ADD = DM9000_MRCMD; st = DM_CMD; status = st; len = 64;/ DM_CMD; Printf(st=%x status=%x len= %xrn,st,status,len); if( (len 1522)/!(status & 0xbf) & for(i=0; i 8) & 0x0ff; elsereturn 0;if(len 1000) return 0;/ if( (HON( ETHBUF-type ) != ETHTYPE_ARP) & (HON( ETHBUF-type ) != ETHTYPE_IP) )/return 0; packet_len = len;return len;在发送封包之前,需要将其中的数据存放在DM9000传送内存0000h0BFFh。当超过0BFFh时,位置自动回到0000h的位置。封包的数据存放在MWCND中,芯片会吧数据自动的存入传送内存的。其封包的大小存放在低字节的TXPLL和高字节的TXPLH中。然后把TCR bit()设置成1,开始传送封包。完成后,将是否完成的信息存入TSRI、TSRII中。其顺序为TSRI-TERII-TSRI循环。故需按照NSR bit-3来判断完成进度。以下是发送数据包的流程图和程序:开始初始化包长不小于60字节?设置源端物理地址将数据依次写入MWCMD寄存器将封包长度写入TXPLL和TXPLH中启动发送等待发送结束发送成功?返回设定长度为60字节查错重发NYN最多发重发5次 DM9000发送封包流程以上是发送数据包,过程很简单。/发送数据包/参数:datas为要发送的数据缓冲区(以字节为单位),length为要发送的数据长度(两个字节)。void DM9000_sendPcket(uint8 *datas, uint32 length)uint32 len,i;uint8 tmp;Printf(发送数据rn);dm9000_reg_write(DM9000_IMR,0x80);/先禁止网卡中断,防止在发送数据时被中断干扰len = length;/把发送长度写入/*这两句是将要发送数据的长度告诉DM9000的寄存器*/ dm9000_reg_write(DM9000_TXPLH, (len8) & 0x0ff); dm9000_reg_write(DM9000_TXPLL, len & 0x0ff); DM_ADD = DM9000_MWCMD;/将要发送的数据写到DM9000的内部SRAM中的写FIFO中 for(i=0; ilen; i+=2)/16 bit mode udelay(2); DM_CMD = datasi | (datasi+18); dm9000_reg_write(DM9000_TCR, 0x01);/发送数据到以太网上 while(1)/等待数据发送完成 uint8 data; data = dm9000_reg_read(DM9000_TCR);/DM9000_NSR if(data&0x01) = 0x00) break; tmp = dm9000_reg_read(DM9000_NSR); if(tmp & 0x01) = 0x04) if(dm9000_reg_read(DM9000_TSR1)&0xfc) = 0x00) Printf(TSR1成功rn); else Printf(TSR1失败rn); else if(dm9000_reg_read(DM9000_TSR2)&0xfc) = 0x00) Printf(TSR2成功rn); else Printf(TSR2失败rn); dm9000_reg_write(DM9000_NSR, 0x2c);/清除状态寄存器,由于发送数据没有设置中断,因此不必处理中断标志位 dm9000_reg_write(DM9000_IMR, 0x81);/DM9000网卡的接收中断使能Printf(发送数据完成rn);TQ2440串口初始化程序:static int whichUart=0;void Uart_Init(int pclk,int baud) int i; if(pclk = 0) pclk = PCLK; rUFCON0 = 0x0; /UART channel 0 FIFO control register, FIFO disable rUFCON1 = 0x0; /UART channel 1 F
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 考点解析-人教版八年级物理《压强》章节测试试题(含答案解析版)
- 起重设备安装工艺流程优化方案
- 建筑预应力长期稳定性分析
- 环保设备选择与安装技术方案
- 考点解析-人教版八年级上册物理声现象《声音的特性》同步测评试卷(附答案详解)
- 无人机行业应用技术创新研讨
- 达标测试人教版八年级上册物理光现象《光的直线传播》专项训练试卷(含答案详解)
- 钢结构工程施工噪声管理方案
- 考点解析人教版八年级上册物理《机械运动》专题练习试卷(含答案详解版)
- 解析卷-苏科版八年级物理下册《物质的物理属性》同步练习试卷(含答案详解版)
- T-CECS 10400-2024 固废基胶凝材料
- 2025年内蒙古三新铁路有限责任公司招聘笔试参考题库含答案解析
- 第十四章其他原因引起的语言障碍讲解
- 2025-2030年中国铝合金游艇行业十三五规划与发展建议分析报告
- 2023-2024学年鲁教版 九年级数学上册期中复习检测试卷
- 船舶机舱进水的应急处理
- 《人体的经络》课件
- 班级管理(延边大学)知到智慧树章节答案
- 《福禄贝尔》课件
- 带班育人方略班会-《从“埋头苦干”走向“抬头巧干”》【课件】
- 【MOOC】人工智能原理-北京大学 中国大学慕课MOOC答案
评论
0/150
提交评论