Chinaunix首页 | 论坛 | 博客
  • 博客访问: 132953
  • 博文数量: 55
  • 博客积分: 1870
  • 博客等级: 上尉
  • 技术积分: 540
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-21 20:51
文章分类

全部博文(55)

文章存档

2011年(27)

2009年(3)

2008年(25)

我的朋友

分类: C/C++

2011-05-04 14:10:57

声明:本文转载于http://www.cnblogs.com/kingst,版权归黑金动力社区(http://www.heijin.org)所有。

P8062389

这一章,我们简单研究一下基于NIOS II的uC/OS系统的开发过程。实验中有三个任务:第一个任务用于实时时钟DS1302驱动,第二个任务用于LED灯闪烁;第三个任务用于数码管显示654321;最终通过把数据通过PC机串口显示出来,有兴趣的可自行把开发板上的其它功能添上。

1uC/OSII简介

u C / O S 是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。

μC/OS-II 的前身是μC/OS,最早出自于1992 年美国嵌入式系统专家Jean J.Labrosse 在《嵌入式系统编程》杂志的5 月和6 月刊上刊登的文章连载,并把μC/OS 的源码发布在该杂志的B B S 上。

μC/OS 和μC/OS-II 是专门为计算机的嵌入式应用设计的, 绝大部分代码是用C语言编写的。CPU 硬件相关部分是用汇编语言编写的、总量约200行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的CPU 上。用户只要有标准的ANSI 的C交叉编译器,有汇编器、连接器等软件工具,就可以将μC/OS-II嵌人到开发的产品中。μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点, 最小内核可编译至 2KB 。μC/OS-II 已经移植到了几乎所有知名的CPU 上。

严格地说uC/OS-II只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。没有提供输入输出管理,文件系统,网络等额外的服务。但由于uC/OS-II良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。

uC/OS-II目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。

1.1任务管理

uC/OS-II 中最多可以支持64 个任务,分别对应优先级0~63,其中0 为最高优先级。63为最低级,系统保留了4个最高优先级的任务和4个最低优先级的任务,所有用户可以使用的任务数有56个。

uC/OS-II提供了任务管理的各种函数调用,包括创建任务,删除任务,改变任务的优先级,任务挂起和恢复等。

系统初始化时会自动产生两个任务:一个是空闲任务,它的优先级最低,该任务仅给一个整形变量做累加运算;另一个是系统任务,它的优先级为次低,该任务负责统计当前cpu的利用率。

1.2 时间管理

uC/OS-II的时间管理是通过定时中断来实现的,该定时中断一般为10毫秒或100毫秒发生一次,时间频率取决于用户对硬件系统的定时器编程来实现。中断发生的时间间隔是固定不变的,该中断也成为一个时钟节拍。

uC/OS-II要求用户在定时中断的服务程序中,调用系统提供的与时钟节拍相关的系统函数,例如中断级的任务切换函数,系统时间函数。

1.3 内存管理

在ANSI C中是使用malloc和free两个函数来动态分配和释放内存。但在嵌入式实时系统中,多次这样的操作会导致内存碎片,且由于内存管理算法的原因,malloc和free的执行时间也是不确定。

uC/OS-II中把连续的大块内存按分区管理。每个分区中包含整数个大小相同的内存块,但不同分区之间的内存快大小可以不同。用户需要动态分配内存时,系统选择一个适当的分区,按块来分配内存。释放内存时将该块放回它以前所属的分区,这样能有效解决碎片问题,同时执行时间也是固定的。

1.4 任务间通信与同步

对一个多任务的操作系统来说,任务间的通信和同步是必不可少的。uC/OS-II中提供了4中同步对象,分别是信号量,邮箱,消息队列和事件。所有这些同步对象都有创建,等待,发送,查询的接口用于实现进程间的通信和同步。

1.5 任务调度

uC/OS-II 采用的是可剥夺型实时多任务内核。可剥夺型的实时内核在任何时候都运行就绪了的最高优先级的任务。

uC/os-II的任务调度是完全基于任务优先级的抢占式调度,也就是最高优先级的任务一旦处于就绪状态,则立即抢占正在运行的低优先级任务的处理器资源。为了简化系统设计,uC/OS-II规定所有任务的优先级不同,因为任务的优先级也同时唯一标志了该任务本身。

uC/OS-II详细用法可参考相关资料。

2FPGA下的uC/OS-II

下面就介绍怎样在以黑金开发板EP2C208上进行uC/OSII实验。

第一步:添加一个用于系统时钟节拍的定时器timer_ucos,定时时间为100ms(根据任务定)。

第二步:在Nios下设置相关选项。请看下面操作步骤。

打开Quart II工程,以黑金开发板EP2C208的工程为例,进入SOPC Builder界面下如图:

clip_image002

在左侧的“System Contents”下单击Peripherais的左侧“clip_image004”;在弹出的菜单下单击Microcotroller Peripherais的左侧“clip_image004[1]”;如下图。

clip_image006

找到 “Interval Timer”并双击,弹出如下图并按下图进行相关设置,单击完成。

clip_image008

命名为timer_ucos;如下图。

clip_image010

时钟节拍定时器到此已添加完成,单击Generate按钮生成SOPC系统。

接下来对Quart II工程进行编译并把 “.pof”通过AS接口下接到EPCS中。至此Quart II工程工作完毕.。

拉下来对Nios工程进行设置。如果没有关闭SOPC界面,可点击“System Generation”下的Nios ii IDE按钮即可进行Nios工程,前提是安装了Nios ii 软件。

新建一个Nios II工程,单击“File”菜单下“New”下的“Nios II C/C++ Application”如下图。

clip_image012

进入后出现如下图,并按图中参数设置(注ucosII为工程名,ep2c8q为SOPC系统,Micro uC/OS-II tutorial为uCOS-II模板)。

clip_image014

单击Next按钮后按下图设置后单击Finish。

clip_image016

接下来对工程进行基本的设置,右击uCOSII选择弹出菜单中的“System Library Properties”出现如下界面并按照如下参数设置。然后单击OK。

clip_image018

把ucosii_tutorial.c中文件内容用下面代码代替。

001/*
002 * =====================================================================================
003 *
004 *       Filename:  ds1302.c
005 *
006 *    Description:  DS1302驱动
007 *
008 *        Version:  1.0.0
009 *        Created:  2010.4.16
010 *       Revision:  none
011 *       Compiler:  Nios II 9.0 IDE
012 *
013 *         Author:  马瑞 (AVIC)
014 *          Email:  avic633@gmail.com 
015 *
016 * =====================================================================================
017 */
018 
019#include
020#include
021#include
022#include "includes.h"
023#include "alt_ucosii_simple_error_check.h"
024#include"ds1302.h"
025#include "altera_avalon_pio_regs.h"
026#include "altera_avalon_timer_regs.h"
027#include "alt_types.h"
028#include "sys/alt_irq.h"
029//定义椎栈
030#define   TASK_STACKSIZE     2048
031OS_STK    initialize_task_stk[TASK_STACKSIZE];
032OS_STK    ds1302_task_stk[TASK_STACKSIZE];
033OS_STK    led_task_stk[TASK_STACKSIZE];
034OS_STK    seg_task_stk[TASK_STACKSIZE];
035//定义优先级
036#define INITIALIZE_TASK_PRIORITY   6
037#define LED_TASK_PRIORITY    10
038#define DS1302_TASK_PRIORITY    11
039#define SEG_TASK_PRIORITY    12
040//格式为: 秒 分 时 日 月 星期 年
041unsigned char time[7] = {0x00,0x19,0x14,0x17,0x03,0x17,0x10};
042unsigned char ti[][7]={"一","二","三","四","五","六","日"};
043alt_u8 segtab[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
044unsigned char bittab[6]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
045unsigned char led_buffer[8]={1,2,3,4,5,6,7,8};
046static unsigned char cnt=0;
047void seg_handler(void);
048 
049/*
050 * ===  FUNCTION  ======================================================================
051 *         Name:  ds1302_task
052 *  Description:  任务1 调用ds1302驱动并通过串口显示数据 
053 * =====================================================================================
054 */ 
055void ds1302_task(void* pdata)
056{
057    INT8U return_code = OS_NO_ERR;
058    ds1302.set_time(time);
059    printf("Hello from Nios II!\n");
060     
061    while(1){
062        printf("Hello from Nios II!\r\n");
063        ds1302.get_time(time);  
064        printf("%02d-%02d-%02d %02d:%02d:%02d 星期%s\r\n",
065        time[6],time[4],time[3],time[2],time[1],time[0],ti[time[5]-1]);
066         
067        OSTimeDlyHMSM(0, 0, 1, 0);
068    }
069     
070}
071/*
072 * ===  FUNCTION  ======================================================================
073 *         Name:  led_task
074 *  Description:  任务2 调用LED驱动并通过串口显示数据
075 * =====================================================================================
076 */ 
077void led_task(void* pdata)
078{
079    INT8U return_code = OS_NO_ERR; 
080    unsigned int num=0;
081    LED->DATA =0xffffffff;
082   
083    while (1){  
084        printf("led is running!\r\n"); 
085         
086        if(num%2==0)
087          LED->DATA =0xffffffff;
088        else LED->DATA =0;
089        num++;
090     
091        OSTimeDlyHMSM(0, 0, 2, 0);
092    }
093}
094/*
095 * ===  FUNCTION  ======================================================================
096 *         Name:  seg_task
097 *  Description:  任务3 调用数码管驱动并通过串口显示数据
098 * =====================================================================================
099 */ 
100void seg_task(void* pdata)
101{
102    INT8U return_code = OS_NO_ERR; 
103    unsigned int numseg=0;
104     
105    while (1){  
106        numseg++; 
107        seg_handler();
108        OSTimeDlyHMSM(0, 0, 0, 300);
109    }
110}
111/*
112 * ===  FUNCTION  ======================================================================
113 *         Name:  seg_handler
114 *  Description:  
115 * =====================================================================================
116 */ 
117 void seg_handler(void)
118{
119    IOWR_ALTERA_AVALON_PIO_DATA(SEG_SEL_BASE, 0xff);
120    IOWR_ALTERA_AVALON_PIO_DATA(SEG_SEL_BASE, bittab[cnt]);
121 
122    IOWR_ALTERA_AVALON_PIO_DATA(SEG_DAT_BASE, segtab[led_buffer[cnt]]);
123 
124    cnt++;
125    if(cnt==6)
126        cnt=0;  
127}
128/*
129 * ===  FUNCTION  ======================================================================
130 *         Name:  main
131 *  Description:  
132 * =====================================================================================
133 */ 
134void  initialize_task(void* pdata)
135{
136    INT8U return_code = OS_NO_ERR; 
137    initCreateTasks();
138   
139    return_code = OSTaskDel(OS_PRIO_SELF);
140    while (1);
141}
142 
143/*
144 * ===  FUNCTION  ======================================================================
145 *         Name:  main
146 *  Description:  
147 * =====================================================================================
148 */ 
149int main (int argc, char* argv[], char* envp[])
150{
151    INT8U return_code = OS_NO_ERR;
152    
153    return_code = OSTaskCreateExt(initialize_task,
154                             NULL,
155                             (void *)&initialize_task_stk[TASK_STACKSIZE],
156                             INITIALIZE_TASK_PRIORITY,
157                             INITIALIZE_TASK_PRIORITY,
158                             initialize_task_stk,
159                             TASK_STACKSIZE,
160                             NULL,
161                 0);
162    OSStart();
163    return 0;
164}
165 
166/*
167 * ===  FUNCTION  ======================================================================
168 *         Name:  initCreateTasks
169 *  Description:  
170 * =====================================================================================
171 */ 
172int initCreateTasks(void)
173{
174    INT8U return_code = OS_NO_ERR;
175    return_code = OSTaskCreateExt(ds1302_task,
176                             NULL,
177                             (void *)&ds1302_task_stk[TASK_STACKSIZE],
178                             DS1302_TASK_PRIORITY,
179                             DS1302_TASK_PRIORITY,
180                             ds1302_task_stk,
181                             TASK_STACKSIZE,
182                             NULL,
183                             0);
184    return_code = OSTaskCreateExt(led_task,
185                             NULL,
186                             (void *)&led_task_stk[TASK_STACKSIZE],
187                             LED_TASK_PRIORITY,
188                             LED_TASK_PRIORITY,
189                             led_task_stk,
190                             TASK_STACKSIZE,
191                             NULL,
192                             0);
193    return_code = OSTaskCreateExt(seg_task,
194                             NULL,
195                             (void *)&seg_task_stk[TASK_STACKSIZE],
196                             SEG_TASK_PRIORITY,
197                             SEG_TASK_PRIORITY,
198                             seg_task_stk,
199                             TASK_STACKSIZE,
200                             NULL,
201                             0);
202    return 0;
203}

编译Nios II工程,下载到EPCS中,下载的方法前面章节讲过,这里就不再重复了。下面是PC机上串口调试工具上的数据。在开发板上还可以看到四个LED灯在闪烁和数码管显示654321。

clip_image040

阅读(3842) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~