ImageVerifierCode 换一换
格式:DOCX , 页数:25 ,大小:223.44KB ,
资源ID:29725231      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/29725231.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(ucos操作系统在ARM上的移植.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

ucos操作系统在ARM上的移植.docx

1、ucos操作系统在ARM上的移植UC/OS-II嵌入式系统在ARM上的移植UC/OS-II操作系统是一款完全公开的源代码,它非常精简,整个操作系统的代码只有几千行,是专门针对于嵌入式开发而产生的一款代码。它有几个特点,分别是可移植性(Portable)、可固化(ROMable)、可裁剪(Scalable)、多任务、可确定性、任务栈、系统服务、中断管理、稳定性可靠性。UC/OS-II主要就是一个内核,由ANSIC语言编写而成。负责任务管理和任务调度,没有文件系统和界面系统。它的代码是公开的,系统的实时性强、移植性好、可多任务。UC/OS-II作为基于优先级的抢占式多任务的实时操作系统,包含了实时

2、内核、任务管理、时间管理、任务间通信同步和内存管理的功能。它使得任务的独立性,不相互干涉,非常的准时和高效,且易于设计和扩展。UO/OS-II共有16个内核文件,11个与CPU类型无关,就是说可以直接使用不需要修改。还有3个内核文件与CPU有关系,要根据需要作出相应的改动。剩下的两个内核文件和具体的应用有关。如图所示UC/OS-II的16个内核文件的层次。C/OS-II内核文件多任务操作的核心是系统调度器,利用TCB来管理任务调度功能。它的主要功能是保存任务的当前态、优先级、等待事件、代码起始地址、初始堆栈指针等。程序的设计关键就是确定划分多任务的问题,以及任务优先级和任务通信。优先级的意思是

3、每个任务都是无限循环的,有运行态度、就绪态、休眠态、挂起态和中断五种状态。当有高一级优先级的任务就绪后,低优先级立即停止运行,转为挂起态或就绪态。这就是可剥夺型的内核。当中断一个高优先级任务,中断时挂起,中断结束后任务继续运行,并立即剥夺低优先级的任务。对于这种可剥夺型内核,CPU的使用时可以确定的,可优化任务级响应。在很多单片机或ARM板上很容易就可以移植UC/OS-II。当然本次设计使用的TQ2440,也可以完美的移植它。移植程序在网上都可以找得到,所以设计中就不做解释了。本次设计实现的是串口协议和网口协议组合成的一个数据网关。其主要的流程图如下所示: 如图所示可以很清楚的看出内核操作系统

4、对于整个系统的控制过程,下面我们要介绍一下UC/OS-II里面的一些程序。用户应用程序任务定义代码如下:void MyTask( void *pdata) /开始定义用户任务 for(;) . void main() TargetInit(); /完成初始化目标开发板。 OSInit (); /完成初始化UCOS-II。 OSTimeSet(0); /完成初始化系统时基。 OSTaskCreate (MainTask,(void *)0, &MainTaskStkMainTaskStkLengh - 1, MainTaskPrio); /开始创建系统初始任务。 OSStart (); /整个任

5、务开始。 return 0;void Task0(void *pdata) /主任务建立:taks0 和 task1 #if OS_CRITICAL_METHOD = 3 /* 分配CPU状态寄存器*/ OS_CPU_SR cpu_sr; #endif OS_ENTER_CRITICAL(); Timer0Init(); /初始化报时信号 ISRInit(); /初始化中断优先级 OS_EXIT_CRITICAL(); OSPrintfInit(); /用户任务给串口 DM9000_init(); OSStatInit(); while(1) OSPrintf(nEnter Main Task

6、n); /测试Dm9000 /打印DM9000寄存器 OSTimeDly(OS_TICKS_PER_SEC); 需要注意的是,C/OS-II的应用程序要使用空闲任务OSTaskldle(),而它是不可删除的系统文件。下面开始对应用程序进行移植了。本次设计是在ARM开发板上实现串口、网口数据转换的的功能。在TQ2440上有串口和网口。通信过程简单的描述就是PC串口发送数据给ARM板,ARM接到串口数据后,从网口再传给PC。相反也是同样的道理,由网口发送数据,有ARM控制由串口发回数据。首先是TCP/IP协议的移植。在编写移植程序前,有必要解释一下基本的协议栈作用和意义。就常见的网络通信方式一般来

7、说有两种:1、UART-RS232,此时只需要pc上有串口调试助手即可。2、TCP/IP,这时候和普通pc与pc通信一样 可以用socket套接字编程也可用别人写好的软件侦听。而现在我们要实现的是串口控制单片机与PC机的通信,在这里用PC来代替以太网。接下来还要介绍一下以太网接口。以太网技术如今已经相当的成熟了,其相应的网络产品价格低廉、技术完善。而数据总线如今越来越难以满足人们日益提升的需要,这时以太网控制网络技术得到了快速的发展,并形成了现场总线的新标准。加上国内大部分局域网是以太网,给予以太网实现现场总线有了雄厚的物质基础。以太网的接口就是以太网同信的基础,是通信介质通信的中间处理部件,

8、实现报文的发送与接收功能,位于TCP/IP协议栈的数据链路层。每一个以太网接口(有时候也叫网卡),在连通后就可以随时的发送和接收网络上的数据,执行EEE802.3标准。TCP/IP对应的ISO结构如图所示: TCP/IP协议栈而单片机与计算机的TCP/IP协议的实现也有很大的不同,原本在计算机里编写的程序可以不考虑代码的大小和效率,但在嵌入式开发板上都要考虑到这些问题。在操作系统、内存分配、指针、参数传递、协议支持以及硬件接口的设计方面有些不同。首先就是操系统,嵌入式的特点之一就是简洁高效,有很强的专业功能。相对而言计算机上的操作系统的侧重点就是兼容性,所以资源要求全面支持,所以很复杂。其次就

9、是内存上的分配,计算机像windows系统它的内存分配是动态的,而在单片机上却不能同样如此,应为RAM的容量所限,所以其中存放以太网的数据包是固态的。由于ARM相对于单片机的能力而言有了很大的提升,所以可以突破单片机的一些约束。如下图所示,TCP/IP协议栈中的内容,从上往下分别对应应用层、传输层、网络层和网络接口层。 TCP/IP协议栈在本次设计中采用Lwip协议栈来实现ARM与以太网的连接。完成移植后,需要介绍一下以太网的初始化过程和数据收发过程。LWIP的初始化要在UC/OS-II之后,在其它任务创建之前。因为LWIP要对以太网协议栈初始化以及新线程的建立,LWIP初始化如图所示。LWI

10、P程序可以实现很多功能,在本设计中没有实现他的全部功能。而简单的PING通需要DM9000来实现。以太网的接收是通过中断方式,如果有数据进入以太网中断函数。其主要任务就是读取和分析数据包。如果数据有效则在Tcpip_input()函数把数据发送出去,并在LWIP初始化创建的线程中就可以得到此消息。然后通过ip_input()函数进入传输层后,再把把数据传到应用层。具体流程如下图所示:为什么要选择DM9000网络驱动器呢?如今嵌入式中大量使用10/100M的以太网卡,实际上并不实用。因为它不能既满足快速传输速率又满足成本控制。这时,DM9000作为一种综合低成本的单一快速以太网控制芯片就有了很高

11、的实用价值。它具有通用的接口,设计简单,可满足不同系统的软件驱动。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

12、_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,0x

13、ff,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,

14、168, 1, 100 /接收端协议地址;#define DM9KS_ID 0x90000A46#define DM9KS_VID_L 0x28#define DM9KS_VID_H 0x29#define DM9KS_PID_L 0x2A#define DM9KS_PID_H 0x2B#define DM9KS_BASE_ADDR_ETH0 0x20000000/nGCS4#define DM9KS_Index (*(volatile unsigned short *)(DM9KS_BASE_ADDR_ETH0 + 0x300)#define DM9KS_Data (*(volatile u

15、nsigned short *)(DM9KS_BASE_ADDR_ETH0 + 0x304)接下是来对DM9000进行初始化的程序部分:void DM9000_init(void) uint32 i; /Test_DM9000AE(); IOSetInit(); /设置中断EINIT7 /初始化设置步骤: 1 dm9000_reg_write(DM9000_GPCR, 0x01); /设置GPCR(1EH) bit0=1,使DM9000的GPIO3为输出。 dm9000_reg_write(DM9000_GPR, 0x00); /GPR bit0=0 使DM9000的GPIO3输出为低以激活内

16、部PHY。 udelay(5000); /延时2ms以上等待PHY上电。 /初始化设置步骤: 2 dm9000_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); /以上完成了DM

17、9000的复位操作 /初始化设置步骤: 3 dm9000_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); /接收FI

18、FO门限3k 8k dm9000_reg_write(DM9000_FCR, 0xff); dm9000_reg_write(DM9000_SMCR, 0x00); /以上是功能控制 /初始化设置步骤: 5 for(i=0; i6; i+) dm9000_reg_write(DM9000_PAR + i, mac_addri);/mac_addr自己定义一下吧,6个字节的MAC地址 /以上存储MAC地址(网卡物理地址)到芯片中去,这里没有用EEPROM,所以需要自己写进去 /初始化设置步骤: 6 dm9000_reg_write(DM9000_NSR, 0x2c); /清除各种状态标志位 dm

19、9000_reg_write(DM9000_ISR, 0x3f); /清除所有中断标志位 /初始化设置步骤: 7 dm9000_reg_write(DM9000_IMR, 0x81); /中断使能 /中断使能(或者说中断屏蔽),即开启我们想要的中断,关闭不想要的,这里只开启的一个接收中断 udelay(10000); /延时2ms以上等待PHY上电。 /PrintfDM9000Reg(); Printf(DM9000初始化完毕rn);接下来是数据包的接收和发送流程图和程序:DM9000收到封包,置于接收内存的0C00h-3FFFh。若超过最大值时,会自动把位置移到0C0h0位置。每个封包有4字

20、节是存放一些与封包相关的信息。若内存的第1字节值为“01h”,表明封包已经在内存中了。在读取其它字节前,先要确定第2个字节,则是这个封包的相关信息。如下图是DM9000接收封包流程: DM9000接收封包流程如图可以看出,DM9000从网络中接到一个数据包后,在数据包前面加了4个字节,分别为“01H”、“status”、“LENL”(包长的低8位)、“LENH”(包长的高8位)。这4个字节来确定数据包的状态,“01H”表示接下来的是有效数据包,“00H”则表示没有数据包,其它值则表示没有正确初始化,并重新初始化。若数据包长度小于60字节,则DM9000芯片会自动为不足的字节补上0。同时,在接收

21、到的包后程序还会自动添加4个CRC校验字节。于是,接收到的数据包至少为64字节。也根据TCP/IP协议从首部字节中找出有效字节数,这就是TCP/IP协议栈的功能了。具体程序如下:/接受数据包/参数:datas为接收到是数据存储位置(以字节为单位)/返回值:接收成功返回数据包类型,不成功返回0uint32 receivepacket(uint8 *datas) uint16 i,tmp,status,len; uint8 ready; uint32 st; ready = 0; /希望读取到01H status = 0; /数据包状态 len = 0; /数据包长度 if(dm9000_reg_

22、read(DM9000_ISR) & 0x01) dm9000_reg_write(DM9000_ISR, 0x01); /清除接收中断标志位 ready = dm9000_reg_read16(DM9000_MRCMDX); / 第一次读取,一般读取到的是 00H Printf(ready1 = %xrn,ready); if(ready & 0x0ff) != 0x01) ready = dm9000_reg_read16(DM9000_MRCMDX); / 第二次读取,总能获取到数据 Printf(ready2 = %xrn,ready); if(ready & 0x01) != 0x0

23、1) 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=

24、%x status=%x len= %xrn,st,status,len); if( (len 1522)/!(status & 0xbf) & for(i=0; i 8) & 0x0ff; else return 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。当超过0BF

25、Fh时,位置自动回到0000h的位置。封包的数据存放在MWCND中,芯片会吧数据自动的存入传送内存的。其封包的大小存放在低字节的TXPLL和高字节的TXPLH中。然后把TCR bit()设置成1,开始传送封包。完成后,将是否完成的信息存入TSRI、TSRII中。其顺序为TSRI-TERII-TSRI循环。故需按照NSR bit-3来判断完成进度。以下是发送数据包的流程图和程序: DM9000发送封包流程以上是发送数据包,过程很简单。/发送数据包/参数:datas为要发送的数据缓冲区(以字节为单位),length为要发送的数据长度(两个字节)。void DM9000_sendPcket(uint

26、8 *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; /将要发送的数

27、据写到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 & 0x

28、01) = 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); /

29、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 FIFO control register, FIFO disable rUFCON2 = 0x0; /UART channel 2 FIFO control register, FIFO disable rUMCON0 = 0x0; /UART chaneel 0 MODEM c

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1