当前位置:文档之家› ucos指导书

ucos指导书

ucos指导书
ucos指导书

第1章EL-ARM-820实验系统的资源介绍

ARM实验箱硬件资源概述

EL-ARM-820型教学实验系统属于一种综合的教学实验系统,该系统采用了目前在国内普遍认同的ARM7TDMI核,32位微处理器,实现了多模块的应用实验。它是集学习、应用编程、开发研究于一体ARM实验教学系统。用户可根据自己的需求选用不同类型的CPU适配板,在不需要改变任何配置情况下,完成从ARM7到ARM9的升级,同时,实验系统上的Tech_V总线能够拓展较为丰富的实验接口板。用户在了解Tech_V标准后,更能研发出不同用途的实验接口板。除此之外,在实验板上有丰富的外围扩展资源(数字、模拟信号发生器,数字量IO输入输出,语音编解码、控制对象、人机接口等单元),可以完成ARM的基础实验、算法实验、控制对象实验和数据通信实验、以太网实验。

图1-1 EL-ARM-820实验教学系统的功能框图

1.1 实验系统的硬件资源总揽

☆CPU单元:内核ARM7TDMI,芯片三星的S3C44B0X,工作频率最高66MHz;

☆线性存储器:2MB,芯片SST39VF160;

☆动态存储器:16MB,芯片HY57V641620;

☆海量存储器:16MB,芯片K9F2808;

☆ USB单元: 1个主接口,两个设备接口,芯片SL811H/S,PDIUSBD12;

☆网络单元: 10M以太网,芯片RTL8019AS;

☆ UART单元: 2个,最高通信波特率115200bps;

☆语音单元: IIS格式,芯片UDA1341TS,采样频率最高48KHz;

☆ LCD单元: 5.7寸,256色,320X240像素;

☆触摸屏单元:四线电阻屏,320X240,5.7寸;

☆ SD卡单元:通信频率最高25MHz,芯片W86L388D,兼容MMC卡;

☆键盘单元: 4X4键盘,带8位LED数码管;芯片HD7279A;

☆模拟输入输出单元:8个带自锁的按键,及8个LED发光管;

☆ A/D转换单元:芯片自带的8路10位A/D,满量程2.5V;

☆步进电机单元:两相四拍式,步距角1.8°,0.1安;

☆直流电机单元:有刷;

☆温度控制单元:集成温控模块;

☆信号源单元:波形三种,频率20-120KHz,三路输出;

☆标准键盘及PS2鼠标接口;

☆标准的IDE硬盘接口;

☆达盛公司的Tech_V总线接口;

☆调试接口: 20针JTAG;

☆CPLD单元;

☆电源模块单元。

1.2 核心板的资源介绍

1.核心板的硬件资源(ARM7TDMI核)

在核心CPU板上包括下列单元和芯片,32位ARM7TDMI的处理器,即三星的S3C44B0芯片,两片动态存储器,每片8M字节,一片2M字节线性flash存储器,一片16M字节的NAN_flash存储器,一个USB主从芯片,完成USB的主从通信选择,

一个10M的以太网控制芯片,完成网络访问功能,一个UART接口,完成串口通信,最高波特率率为115200bps, 一个RTC实时时钟,一个5V转3.3V和2.5V的电源管

表1-1

表1-2

表1-3

表1-4

2.核心板资源的具体介绍

1)电源模块

在S3C44B0 CPU板上由于其内核采用2.5V,I/O接口采用3.3V供电,因此需要将通用的5V转换成2.5V和3.3V。图1-2为使用LM1117电源转换芯片把5V转成3.3V和2.5V 的转换电路。

图1-2

2)线性flash存储器单元

该存储单元在板卡上标号为U9,选用2MB字节的 SST39VF160,16位数据总线,片选接NGCS0,CPU分配给它的地址空间为0x00000000—0x001fffff,也就是S3C44BOCPU 的bank0区。启动代码部分则放在从0x00000000开始的地址空间内。程序代码可以在里面执行。

3)NAND_FLASH海量存储器单元

该存储单元在板卡上标号为NAND_FLASH,选用16MB芯片K9F2808。8位数据总线传输,GPC9接其片选信号,CPU分配给它的地址空间为0x04000000—0x005fffff,也就是S3C44BOCPU的bank2区。GPE0接NAND_FLASH的状态监测脚, GPC14接ALE地址锁存使能,GPC15接CLE命令锁存使能。NGCS2也接入该单元。

4)同步动态存储器单元

该存储单元在板卡上标号为U10,U11。选用两片8MB字节的 HY57V641620,16位数据总线。片选NSCS0接U10单元,片选NSCS1接U11单元,CPU分配给U10单元的地址空间为0x0C000000—0x0C7fffff,也就是S3C44BOCPU的bank6区。CPU分配给U11单元的地址空间为0x0E000000—0x0E7fffff,也就是S3C44BOCPU的bank7区。

5)RS23串口单元

该存储单元在板卡上标号为U2,在板卡的背面,选用了MAX3232CSE电压转换芯片,进行PC机与CPU板的串口通讯。它采用收、发、地,三线连接,无握手信号。D1为向外

部发送数据时的显示灯,D2为接收外部数据时的显示灯。通过S3C44B0X内部的串口0控制器进行控制。

6)主/从USB单元

该存储单元在板卡上标号为U14,选用了SL811H/S主从芯片,8位数据总线传输,片选NGCS1接主/从USB单元,CPU分配给U14单元的地址空间为0x02000000—0x03ffffff,也就是S3C44BOCPU的bank1区。S3C44B0CPU的外部中断ExINT0响应主/从USB中断。GPB4位控制芯片的主/从模式选择。它是软件控制方式。

7)网络单元

该存储单元在板卡上标号为U12,选用了RTL8019AS网络芯片,16位数据总线传输,片选NGCS3接网络单元。CPU分配给U12单元的地址空间为0x06000000—0x07ffffff,也就是S3C44BOCPU的bank3区。S3C44B0CPU的外部中断ExINT1响应该中断。D5和D6为网络的指示灯。

表1-5

8)JTAG单元

JTAG(Joint Test Action Group,联合测试行动小组)是一种国际标准测试协议,主要用于芯片内部测试及对系统进行仿真、调试,JTAG技术是一种嵌入式调试技术,它在芯片内部封装了专门的测试电路TAP(Test Access Port,测试访问口),通过专用的JTAG 测试工具对内部节点进行测试。目前大多数比较复杂的器件都支持JTAG协议,如ARM、DSP、FPGA器件等。标准的JTAG接口是4线:TMS、TCK、TDI、TDO,分别为测试模式选择、测试时钟、测试数据输入和测试数据输出。

通过JTAG接口,可对芯片内部的所有部件进行访问,因而是开发调试嵌入式系统的一种简洁高效的手段。目前JTAG接口的连接有两种标准,即14针接口和20针接口,EL-ARM-820核心上使用的是20针接口。接口定义见表1-6。

表1-6

在核心板上,JTAG的第1脚用一白色的方框标注,当串口、USB口、网络口向左摆放时,第1脚下面的管脚为第2脚,它左面的管脚依次为3,5,...,19;第2脚左面的管脚依次为4,6, (20)

9)核心CPU板上的外接接口单元

在CPU板上有J4,J5,J6,J7,J8,J9,6个外扩接口单元,其中,J4和J5,J6和J7,J8和J9的端口引脚定义相同,现对J4,J7,J9的引脚加以说明。

表1-7

表1-8

J4用来扩展J7、J9没有扩展的CPU信号,如AD输入、液晶、串口等和扩展子板

表1-9

1.3 实验箱底板的资源介绍

1. 概述

实验箱底板上的资源丰富,具体的实验单元有:LCD模块,触摸屏模块,语音单元模块,串口2模块,USB设备模块,电源模块,模拟输入输出模块,键盘模块,CPLD烧写模块,键盘数码管模块,SD(MMC)卡模块,A/D转换模块,步进电机模块,直流电机模块,温控单元模块,信号源发生器模块。以及PS2鼠标键盘接口,IDE硬盘接口,Tech_V 总线接口等等。

实验箱上的底板详细具体资源见表1-10。

表1-10(上页)

接下来详细介绍各模块单元。

2. 底板资源的具体介绍

1)模拟输入输出接口单元

8bit的数字量输入(由八个带自锁的开关产生),通过74LS244缓冲;8bit的数字量输出(通过八个LED灯显示),通过74LS273锁存。数字量的输入输出都映射到CPU的IO空间。数字值的显示的通过八个LED灯和LCD屏,按下一个键,表示输入一个十进制的“0”值,8个键都不按下,则数字量的十进制数值为255,8个键都按下,则数字量的十进制数值为0,通过LED灯,和LCD的显示可以清楚的看到实验结果。

2)键盘数码管模块

键盘接口是由芯片HD7279A控制的,HD7279A是一片具有串行接口的,可同时驱动8位共阴式数码管或(64只独立LED)的智能显示驱动芯片,该芯片同时还可连接多达64键的键盘矩阵,单片即可完成LED显示,键盘接口的全部功能。HD7279A内部含有译码器,可直接接受BCD码或16进制码,并同时具有2种译码方式。此外,还具有多种控制指令,如消隐、闪烁、左移、右移、段寻址等。HD7279A具有片选信号,可方便地实现多于8位的显示或多于64键的键盘接口。在该实验系统中,仅提供了16个键。

3)USB设备模块

USB设备模块,采用了飞利蒲的USB设备控制芯片PDIUSBD12,该芯片遵从USB1.1规范,最高通信率12Mbps,该单元位于实验箱的左下角。D3为通信状态指示灯。使用外部中断4来响应中断请求。

4)串口1模块

串口1模块,采用了美信的MAX202CPE芯片,通过它可以把PC的电信号转换成实验箱可以使用的信号,它的最高串行通信波特率为115200bps.

5)音频模块

语音的模拟信号的编解码采用了UDA1341TS芯片。该芯片有两个串行同步变换通道、D/A转换前的差补滤波器和A/D变换后的滤波器。其他部分提供片上时序和

控制功能。芯片的各种应用配置可以通过芯片的三根线,由串行通信编程来实现。主要包括:复位、节电模式、通信协议、串行时钟速率、信号采样速率、增益控制和测试模式、音质特性。最大采样速率48kb/s。

语音处理单元由UDA1341TS模块、输出功率模块组成。语音的模拟信号经过偏置和滤波处理后输入到语音的编解码芯UDA1341TS中,UDA1341TS以IIS的语音格式送入S3C44B0X中,S3C44B0可以处理也可以不处理该信号,把它保存起来,也可用DMA控制而不经过CPU处理,直接实时的采集,然后实时的播放出去。

音频信号通过D/A转换后输出,经过一次功率放大,然后可以推动功率为0.4W的板载扬声器,也可以接耳机输出。如图1-3。

语音处理单元原理框图

图1-3

语音处理单元接口说明:

LINE_IN:音频输入端子,可输入CD、声卡、MP3等语音信号。

M IC:音频输入端子,麦克风等语音信号。

SPEAKER:音频输出端子,可接耳机、音箱。

语音处理单元旋钮说明:

表1-11

表1-12

6)LCD模块

本实验系统仅选用了LCD液晶显示屏,LCD的控制器使用S3C44B0X的内部集成的控制器,LCD屏选用的是5.7寸,320X240像素,256色的彩屏。电源操作范围宽(2.7V to 5.5V);低功耗设计可满足产品的省电要求。

其中,可调变位器VR2用于调节LCD屏色彩的对比度,产品出厂时,已设定成在室温下较好的对比度,当因温度低或高等因素显示不正常时,可适当调节VR2到合适的色彩。一般请不要调整。

表1-13

“LCD_ON/OFF”按键,控制着LCD屏的电源,是电源的开关。

7)触摸屏模块

触摸屏模块,采用了BB公司的ADS7843芯片,通过它可以把采集到的电压信号经其内部的12位A/D转换成数字量给S3C44B0X处理,在使用触摸屏模块时,要使S2开关的2处在“ON”状态。

表1-14

注:二者只能择其一使用,不能同时使用。

8)SD(MMC)卡单元

SD(MMC)卡单元,采用了华邦公司的W86L388D的SD(MMC)卡的控制器,它的最高时钟率为25MHz,能够使用1线或4线传输数据及指令,它通过初始化配置能够

使用MMC卡。CPU通过给其相应的寄存器中写入控制命令,来驱动它读写SD(MMC)卡,从SD(MMC)卡中读取的数据通过与CPU相连的16位数据总线,发送给CPU处理。SD(MMC)卡与CPU的是通过中断方式来进行应答的,W86L388D的中断控制器则显示SD(MMC)卡的各种中断请求,CPU只须读取其状态,就能判断对SD(MMC)卡进行如何处理。其原理如图1-4。D12,通信状态指示灯,D13卡识别指示灯。

图1-4

9)A/D转换单元

A/D转换单元,采用S3C44B0X内置的A/D转换器,它包含一个8路模拟输入混合器,12位模数转换。最大转换速率:100KSPS,输入电压范围:0-2.5V输入带宽: 0-100 Hz(无采样和保持电路),低的电源消耗。在本实验系统中,模拟输入信号经

转换器,然后转换的数字量给S3C44B0X处理。如图1-5。

过降压、偏置处理后输入A/D

图1-5模数单元原理框图

模数转换单元拨码开关说明见表1-15:

SW3:拨码开关

表1-15

拨码开关其它设置状态为非法状态。

10)信号源单元

ucosII任务切换是怎样实现的

UC/OS-II学习笔记之——任务切换是怎样实现的问题是, o Uc/OS-II如何切换任务?通过任务调度器OS_Sched(),那么谁在调用这个函数? o CPU在这里肯定有作用,因为任务切换必然涉及到CPU寄存器的入栈和出栈, 那么这一块工作是如何完成的? 书上讲:为了做到任务切换,运行OS_TASK_SW(),人为模仿一次中断。中断服务子程序或陷阱处理(trap hardler),也称作事故处理(exception handler),必须给汇编语言函数OSCtxSw()提供中断向量[1.92]。 那么,“人为模仿一次中断”是什么意思? 是指:OS_TASK_SW()触发了一个中断,由中断完成了任务切换? 阅读源代码,查找答案…… #define OS_TASK_SW()OSCtxSw()//这是一个宏调用,定义在os_cpu.h,Os_cpu_a.asm中定义了OSCtxSw NVIC_INT_CTRL EQU0xE000ED04 NVIC_PENDSVSET EQU0x10000000 ;****************************************************************************** ;PERFORM A CONTEXT SWITCH(From task level) ;void OSCtxSw(void) ; ;Note(s):1)OSCtxSw()is called when OS wants to perform a task context switch.This function ;triggers the PendSV exception which is where the real work is done. ;****************************************************************************** OSCtxSw LDR R0,=NVIC_INT_CTRL;Trigger the PendSV exception(causes context switch) LDR R1,=NVIC_PENDSVSET STR R1,[R0] BX LR 注释说明该段汇编代码触发了一个PendSV的异常。

uCOS-II任务堆栈检验(OSTaskStkChk())

uC/OS-II任务堆栈检验(OSTaskStkChk()) 使用OSTaskStkChk()可以返回一个记录所检查堆栈空间的使用情况,包括已使用空间及 空闲空间的大小。但只有用OSTaskCreateExt()建立的任务的堆栈才正常使用OSTaskStkChk()。这个堆栈检验功能的原理很简单,因为OSTaskCreateExt()已经把任务堆栈 每个字节初始为0了,所以只需要从栈底依次扫描每个字节并计数直到当一个字节的内容不 为0,也即从这个字节起的空间已经至少被任务使用过了,得到的计数就是空闲空间的大小,使用空间的大小由栈的总大小减去空闲空间的大小就可以得到。 OSTaskStkChk(INT8U prio,OS_STK_DATA *pdata) /*检查优先级为prio的任务的堆栈使用情况,并把结果存入OS_STK_DATA类型的单元中*/ INT8U OSTaskStkChk(INT8U prio,OS_STK_DATA *pdata) { OS_TCB *ptcb; /*用于执行所要堆栈检测任务的TCB*/ OS_STK *pchk; /*用于指向所要堆栈检测的任务的堆栈*/ INT32U free; /*存放未使用的堆栈容量*/ INT32U size; /*存放堆栈总容量*/ pdata->OSFree=0; /*将用于存放堆栈检测结果的单元进行清零*/ pdata->OSUsed=0; if(prio>OS_LOWEST_PRIO &&prio != OS_PRIO_SELF)/*查看优先级是否在有效范围内*/ { return(OS_PRIO_INVALID); } OS_ENTER_CRITICAL();/*在对任务的TCB内容读取的过程中需要关中断,即TCB是临界资源,不可多个进程同时访问*/ if (prio==OS_PRIO_SELF) /*如果prio的值为OS_PRIO_SELF 即prio==0xFF,系统规定优 先级为当前正在执行的任务*/ { prio=OSTCBCur->OSTCBPrio;/*需要将prio的值更改为当前正在执行任务的优先级*/ } ptcb=OSTCBPrioTbl[prio];/*根据任务的优先级和TCB优先级表,找到所要进程堆栈检测 任务的TCB*/

ucos-ii操作系统复习大纲

ucos-ii操作系统复习大纲 一.填空题 1.uC/OS-II是一个简洁、易用的基于优先级的嵌入式【抢占式】多任务实时内核。 2.任务是一个无返回的无穷循环。uc/os-ii总是运行进入就绪状态的【最高优先级】的任务。 3.因为uc/os-ii总是运行进入就绪状态的最高优先级的任务。所以,确定哪 个任务优先级最高,下面该哪个任务运行,这个工作就是由【调度器(scheduler)】来完成的。 4.【任务级】的调度是由函数OSSched()完成的,而【中断级】的调度 是由函数OSIntExt() 完成。对于OSSched(),它内部调用的是【OS_TASK_SW()】完成实际的调度;OSIntExt()内部调用的是【 OSCtxSw() 】实现调度。 5.任务切换其实很简单,由如下2步完成: (1)将被挂起任务的处理器寄存器推入自己的【任务堆栈】。 (2)然后将进入就绪状态的最高优先级的任务的寄存器值从堆栈中恢复到【寄存器】中。 6.任务的5种状态。 【睡眠态(task dormat) 】:任务驻留于程序空间(rom或ram)中,暂时没交给ucos-ii处理。 【就绪态(task ready)】:任务一旦建立,这个任务就进入了就绪态。 【运行态(task running)】:调用OSStart()可以启动多任务。OSStart()函数只能调用一次,一旦调用,系统将运行进入就绪态并且优先级最高的任务。 【等待状态(task waiting)】:正在运行的任务,通过延迟函数或pend(挂起)相关函数后,将进入等待状态。

【中断状态(ISR running)】:正在运行的任务是可以被中断的,除非该任务将中断关闭或者ucos-ii将中断关闭。 7.【不可剥夺型】内核要求每个任务自我放弃CPU的所有权。不可剥夺型调度法也称作合作型多任务,各个任务彼此合作共享一个CPU。 8.当系统响应时间很重要时,要使用【可剥夺型】内核。最高优先级的任务一旦就绪,总能得到CPU的控制权。 9.使用可剥夺型内核时,应用程序不应直接使用不可重入型函数。调用不可重入型函数时,要满足互斥条件,这一点可以用【互斥型信号量】来实现。 10.【可重入型】函数可以被一个以上的任务调用,而不必担心数据的破坏。 11.可重入型函数任何时候都可以被中断,一段时间以后又可以运行,而相应数据不会丢失。可重入型函数或者只使用【局部变量】,即变量保存在CPU寄存器中或堆栈中。如果使用全局变量,则要对全局变量予以【保护】。 12.每个任务都有其优先级。任务越重要,赋予的优先级应【越高】。 13.μC/OS-Ⅱ初始化是通过调用系统函数【OSIint()】实现的,完成μC/OS-Ⅱ所有的变量和数据结构的初始化。 14.多任务的启动是用户通过调用【OSStart()】实现的。然而,启动μC/OS-Ⅱ之前,用户至少要建立一个应用【任务】。 15. μC/OS-Ⅱ的参数配置文件名为【】。 16.删除任务,是说任务将返回并处于【休眠状态】,并不是说任务的代码被删除了,只是任务的代码不再被μC/OS-Ⅱ调用。 17.μC/OS-Ⅱ要求用户提供【定时中断】来实现延时与超时控制等功能。 18.定时中断也叫做【时钟节拍】,它应该每秒发生10至100次。 19. 时钟节拍的实际频率是由用户的应用程序决定的。时钟节拍的频率越高,系统的负荷就【越重】。 20.μC/OS-II中的信号量由两部分组成:一个是信号量的【计数值】,它是一个16位的无符号整数(0 到65,535之间);另一个是由等待该信号量的任务组成的【等待任务表】。用户要在中将OS_SEM_EN开关量常数置成【1 】,这样μC/OS-II 才能支持信号量。 21. μC/OS-II中表示当前已经创建的任务数全局变量名为:【 OSTaskCtr 】。

实验二 UCOS-II任务管理

班级学号姓名同组人 实验日期室温大气压成绩 实验二 UCOS-II任务管理 一、实验目的 1、掌握UCOS-II中任务管理的函数的应用。 2、掌握UCOS-II在STM32平台下对硬件的控制。 3、掌握开发UCOS-II应用的程序结构。 二、实验步骤 1、UCOSII工作原理 UCOSII提供系统时钟节拍,实现任务切换和任务延时等功能。这个时钟节拍由 OS_TICKS_PER_SEC(在os_cfg.h中定义)设置,一般我们设置UCOSII的系统时钟节拍为1ms~100ms。本次实验利用STM32的SYSTICK定时器来提供UCOSII时钟节拍。 UCOSII的任何任务都是通过一个叫任务控制块(TCB)的东西来控制的,每个任务管理块有3个最重要的参数:(1)任务函数指针;(2)任务堆栈指针;(3)任务优先级。 在UCOSII中,使用CPU的时候,优先级高(数值小)的任务比优先级低的任务具有优先使用权,即任务就绪表中总是优先级最高的任务获得CPU使用权,只有高优先级的任务让出CPU使用权(比如延时)时,低优先级的任务才能获得CPU使用权。UCOSII不支持多个任务优先级相同,也就是每个任务的优先级必须不一样。任务的调度其实就是CPU 运行环境的切换,即:PC指针、SP指针和寄存器组等内容的存取过程 UCOSII的每个任务都是一个死循环。每个任务都处在以下5种状态之一的状态下,这5种状态是:睡眠状态、就绪状态、运行状态、等待状态(等待某一事件发生)和中断服务状态。 睡眠状态,任务在没有被配备任务控制块或被剥夺了任务控制块时的状态。

就绪状态,系统为任务配备了任务控制块且在任务就绪表中进行了就绪登记,任务已经准备好了,但由于该任务的优先级比正在运行的任务的优先级低,还暂时不能运行,这时任务的状态叫做就绪状态。 运行状态,该任务获得CPU使用权,并正在运行中,此时的任务状态叫做运行状态等待状态,正在运行的任务,需要等待一段时间或需要等待一个事件发生再运行时,该任务就会把CPU的使用权让给别的任务而使任务进入等待状态。 中断服务状态,一个正在运行的任务一旦响应中断申请就会中止运行而去执行中断服务程序,这时任务的状态叫做中断服务状态。 UCOSII任务的5个状态转换关系如图所示: 与任务相关的几个函数: 1)建立任务函数 UCOSII提供了我们2个建立任务的函数:OSTaskCreat和OSTaskCreatExt,我们一般用OSTaskCreat函数来创建任务,该函数原型为: OSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INTU prio) 该函数包括4个参数: task:是指向任务代码的指针; pdata:是任务开始执行时,传递给任务的参数的指针; ptos:是分配给任务的堆栈的栈顶指针; prio是分配给任务的优先级。 每个任务都有自己的堆栈,堆栈必须申明为OS_STK类型,并且由连续的内存空间组成。可以静态分配堆栈空间,也可以动态分配堆栈空间。OSTaskCreatExt也可以用来创

uCOS-II中的任务切换机制

uCOS-II中的任务切换机制 【@.1 函数周期与死循环】 一般函数的生命周期很简单,从开始调用函数起,直到函数返回,即结束。这样一来就完成了这个函数的使命,它也就不再需要了。对于一般的函数就是这样,但是回过头想想,对于一个系统、OS、或者工业控制中的一个控制器重的系统个,函数返回是很轻易很随便的就能返回吗?返回就意味着函数结束,死亡,若是想系统这样一个很大的函数,它的返回就意味着系统结束。因此,对于系统的函数返回有些时候我们不希望它返回,返回时是需要好好设计的,像嵌入式中的控制程序我们也并不需要它返回,直接关机就好了。因此,一个系统往往就是一个很大的循环,不停的扫描,而我们编程的时候对于这个死循环是需要好好设计的。考虑以下一个控制要求, @.按键控制电机启、停、正转反转,并每秒发送CAN报文报告当前情况。 我们可以有多种方法实现这一要求: 方法一:每次在循环体重扫描当前按键的电平,从而进入对应的控制电机函数,如果所有电平都没有信号则直接进入下一个循环。发送CAN报文就直接用一个定时中断。这样的好处就是编程简单直白,每次循环进入不同的电机控制函数,坏处很明显,一定要等待到下一个循

环才能进入其他的电机控制函数,每次循环的时间不好控制,不管你用函数指针还是 if/else来判断,每次循环一定要等待电机动作结束才能进入下一个循环。 方法二:改用外部中断来处理按键。仅当按键按下时触发外部中断,从而控制响应的电机进行操作。这样的好处就是循环体简单,可以仅仅就是一个计数器加一,所有控制都等中断来实现。但这样带来的问题也很明显,就是中断嵌套问题。比如当电机正转时按下停止按钮,这时由于是在中断中,停止按钮是否真的能够得到响应?这就涉及到中断嵌套问题,并不见得所有CPU都能支持中断嵌套,我的这一篇文章对中断嵌套问题进行了一个讨论。 方法三:采用RTOS的思想,加入任务调度系统。每次任务调度系统就是一个小小的循环,对于各个任务进行轮询,当这次轮询发现某任务是已经就绪的优先级最高的任务,则交给CPU处理,所有中断与任务,任务与任务之间有通讯机制可以交换信息。当然实际上并不仅仅只在任务调度器轮询时才进行任务的切换,实际上的操作比这个复杂一些,我的这篇文章就想以uCOS-II为例讨论RTOS的任务调度系统是怎样执行的。 【@.2 uCOS-II中的任务调度】 回到前面的方法一,二,我们将这种任务称作前后台任务。

实验二-UCOS-II任务管理

实验二-U C O S-I I任务 管理 -CAL-FENGHAI-(2020YEAR-YICAI)_JINGBIAN

班级学号姓名同组人 实验日期室温大气压成绩 实验二 UCOS-II任务管理 一、实验目的 1、掌握UCOS-II中任务管理的函数的应用。 2、掌握UCOS-II在STM32平台下对硬件的控制。 3、掌握开发UCOS-II应用的程序结构。 二、实验步骤 1、UCOSII工作原理 UCOSII提供系统时钟节拍,实现任务切换和任务延时等功能。这个时钟节拍由 OS_TICKS_PER_SEC(在os_cfg.h中定义)设置,一般我们设置UCOSII的系统时钟节拍为1ms~100ms。本次实验利用STM32的SYSTICK定时器来提供UCOSII时钟节拍。 UCOSII的任何任务都是通过一个叫任务控制块(TCB)的东西来控制的,每个任务管理块有3个最重要的参数:(1)任务函数指针;(2)任务堆栈指针;(3)任务优先级。 在UCOSII中,使用CPU的时候,优先级高(数值小)的任务比优先级低的任务具有优先使用权,即任务就绪表中总是优先级最高的任务获得CPU使用权,只有高优先级的任务让出CPU使用权(比如延时)时,低优先级的任务才能获得CPU使用权。UCOSII不

支持多个任务优先级相同,也就是每个任务的优先级必须不一样。任务的调度其实就是CPU运行环境的切换,即:PC指针、SP指针和寄存器组等内容的存取过程UCOSII的每个任务都是一个死循环。每个任务都处在以下5种状态之一的状态下,这5种状态是:睡眠状态、就绪状态、运行状态、等待状态(等待某一事件发生)和中断服务状态。 睡眠状态,任务在没有被配备任务控制块或被剥夺了任务控制块时的状态。 就绪状态,系统为任务配备了任务控制块且在任务就绪表中进行了就绪登记,任务已经准备好了,但由于该任务的优先级比正在运行的任务的优先级低,还暂时不能运行,这时任务的状态叫做就绪状态。 运行状态,该任务获得CPU使用权,并正在运行中,此时的任务状态叫做运行状态等待状态,正在运行的任务,需要等待一段时间或需要等待一个事件发生再运行时,该任务就会把CPU的使用权让给别的任务而使任务进入等待状态。 中断服务状态,一个正在运行的任务一旦响应中断申请就会中止运行而去执行中断服务程序,这时任务的状态叫做中断服务状态。 UCOSII任务的5个状态转换关系如图所示:

uCOS II 删除任务

任务的删除(删除任务请求方,被删除任务方)所谓删除任务,就是把任务置于睡眠状态。具体做法是,把被删除的任务 的任务控制块从任务控制块链表中删除,并归还给空任务控制块链表。(创建一个任务就像向空任务控制链表借东西。但是有借必有还,删除任务就是用完以后归还给空任务链表的过程),然后在任务就绪表中把该任务的就绪状态位置为0,于是该任务就不能再被调度器所调用了。简单的说,就是把他的身份证给吊销了。 #if OS_TASK_DEL_EN INT8U OSTaskDel(INT8U prio); //要删除任务的优先级别这与任务的挂起相似,可以调用函数OSTaskDel()来删除任务自身或者除了空闲任务之外的其他任务。如果一个任务要删除自己,则应调用函数时函数参数prio为OS_PRIO_SELF。 核心讨论的问题 问题的提出: 有时,任务会占用一些动态分配的内存或是信号量之类的资源。这时,如果有其他任务把这个任务删除了,那么被删除任务所占用的一些资源就会因为没有被释放而丢失,这时任何系统都无法接受的。 这就像在C语言中用malloc申请的对空间,在释放之前不能让子函数没了,否则永远就找不到申请的这段空间了。 解决方案: 提出删除任务请求的任务只能负责提出删除任务的请求,而删除工作要有被删除任务自己来完成。这样,被删除的任务就可以根据自身的具体情况来决定何时删除任务自身,同时也会有机会再删除自身之前把占用的资源给释放掉。 显然如果想使提出删除任务请求的任务和被删除任务之间能够像上述方式来执行删除工作,则他们必须有某种通信方法。ucos利用被删除任务的任务控制块成员OSTCBDelReq作为请求删除方与被删除方的联络信号,同时提供了一个双方都能调用的函数-----请求删除任务函数OSTaskDelReq()。这样提出删除任务请求的任务和被删除任务的双方都能使用这个函数来访问OSTCBDelReq这个信号,从而可以根据这个信号状态来决定各自的行为 过程是这样的。就像两个人A和B。A对B调用函数OSTaskDelReq ()说我要删除你。然后将Flag(OSTCBDelReq)置给一个标志位。B通过函数OSTaskDelReq()看到Flag(OSTCBDelReq)置位,然后就启动自己删除自己的命令。

uCOS-II任务讲解

1.uCos-II操作系统内核的主要工作就是对任务进行管理和调度. 在应用程序设计的角度来看,uCos-II的任务就是一个线程. 2.从任务的存储结构来看,uCOS-II的任务由三个部分组成: 1-任务程序代码(任务的执行部分). 2-任务堆栈(用于保存任务工作环境) 3-任务控制块(用于保存任务属性) 3.uCOS-II的任务有两种,用户任务和系统任务. 由应用程序设计者编写的任务叫做用户任务. 由系统提供的任务叫做系统任务. 用户任务是为解决应用问题而编写的,系统任务是为应用程序来提供某种服务的. 4,任务的5种状态 5.从等待状态不能直接进入运行状态. 6.从程序设计的角度来看,一个uCOS-II任务的代码就是一个C语的函数.为了可以传递各种不同类型的数据甚至是函数,任务的参数是一个void类型的指针.可以说uCOS-II任务是一个代码结构是带有临界段的无限循环. 7.用户任务他不是被主函数或其他函数调用的, 主函数main()只负责创建和启动它们,而操作系统负责来调度运行. 8.OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL用来做临界保护的. 9.OSTaskCreate()为操作系统uCOS-II提供的用来创建任务的函数. 10.OSStart()为操作系统提供启动各任务的函数.启动任务以后,任务就应由操作系统来管理和调度了. 11.uCOS-II预定义了两个为应用程序服务的系统任务:空闲任务和统计任务.其中空闲任务是每个应用程序必须使用的,而统计任务则是应用程序可以根据实际需要来选择使用的. 12.空闲任务:让CPU在没有用户任务可执行时有事可做. OSTaskIdle(): void OSTaskIdle(void *pdata) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; #endif pdata = pdata; //定义了型参没有用,编译器会报警告或者错误 for(;;) { OS_ENTER_CRITICAL(); OSdleCtr++; OS_EXIT_CRITICAL(); } }

ucos任务的各个状态简述

被中断等待事件。时间挂起 1. 运行状态 任何时候只有一个在运行。正在运行的任务可能会因为等待某一个任务而进 入等待状态,此时下一个优先级更高的进入了就绪状态被赋予了CPU 的控制权,即任务级切换。如果一个未屏蔽中断发生,当前任务将进入中断状态,则在中断返回时将进行任务切换,即更到优先级的任务 2. 就绪状态 如果一个任务所等待的资源除CPU 外已全部获得,则处于就绪状态。如果该 任务的优先级最高,则马上执行。如果当前还有高优先级的任务,则次任务等待更高优先级的任务放弃CPU 的控制权后再调度CPU的使用权。 3. 等待状态 即正在运行的任务需要等待某一事件或时间延迟的发生。当任务因等待事件 被挂起时,下一个优先级更高的立即得到CPU的控制权。当其等待的事件发生了,该被挂起的任务重新进入就绪状态。事件发生的报告可能来自另一个任务,也可能来自中断服务子程序。 4. 休眠状态 任务驻留在程序空间中,还没有交给ucos管理,把任务交给ucos 是通 过调用OSTaskCreate ()或OSTaskCreateExt ()两个函数之一实现的。任务一旦确立将进入就绪状态。一个任务可通过调用OSTaskDel ()返回到休眠状态,即被删除,或通过调用该函数让另外一个任务进入休眠状态。 5. 被中断状态 正在运行的任务可以被中断,除非该任务关闭中断,或ucos 关闭中断。被 中断了的任务即进入了中断服务状态。响应中断时,正在执行的任务被挂起,中断服务子程序控制了CPU 的使用权。中断服务子程序可能会报告一个或多个时间的发生,而使一个或多个任务进入就绪状态。此时,中断服务子程序返回之前,ucos 要判定被中断的任务是否还是就绪态任务中优先级最高的。如果更高的进入了就绪状态,则他会运行,否则原来的继续运行。

ucos II 任务通信与同步

任务的同步与一个通信初解 操作系统就像就像一个好的家长,控制着资源的公平分配 应用程序中的各个任务,必须通过彼此之间的有效合作,才能完成一项大规模的工作。因为这些任务在运行时,经常需要相互无冲突地访问一个共享资源,或者需要相互支持和 依赖,甚至有时候还需要互相加以必要的制约,才能保证任务的顺利进行。因此操作系统 必须具有对任务运行进行协调的能力,从而使任务之间可以无冲突,流畅的同步运行,而 不致导致灾难性的后果。 这与人们依靠通信来相互沟通,从而使人际关系和谐,工作顺利的做法是一样的,计算机系统依靠任务间的良好通信来保证任务与任务的同步。 任何为任务所占用的实体都可以称为资源。资源可以是输入输出设备,比如打印机,键 盘显示器,资源也可以是一个变量,一个结构或者是一个数组。 1任务的同步和事件 嵌入式系统中的各个任务是为同一个大的任务服务的子任务,他们不可避免的要共同使 用一些资源,并且在处理一些需要多个任务共同协同来完成的工作时,还需要相互的支持和限制。因此,对一个完善的多任务操作系统来说,系统必须具有完备的同步和通信机制任务的同步: 为了实现各个任务之间的合作和无冲突的运行,在各个任务之间必须建立一些制约关系。其中一种制约关系叫做直接制约关系,另一种制约关系叫做间接制约关系 直接制约关系来自任务的合作:例如,有任务A和任务B两个任务,他们需要通过访 问同一个数据缓冲区合作完成一项工作,任务A负责向缓冲区写入数据,任务B负责向缓 冲区读取该数据。显然,当任务A还未向缓冲区写入数据时(缓冲区为空时),任务B因 不能从缓冲区得到有效地数据而应处于等待状态;只有等任务A向缓冲区写入了数据之后,才应该通知任务B去读取数据。相反,当缓冲区的数据还未被任务B读取时(缓冲区为满时),任务A就不能向缓冲区写入新的数据而应该处于等待状态;只有当任务B自缓冲区读取数据后,才应该通知任务A写入数据。显然,如果这两个任务不能如此协调工作,将势必造成严重的后果。 间接制约关系源于对资源的共享:例如:任务A和任务B共享一台打印机,如果系统已经把打印机分配给了任务A,则任务B因不能获得打印机的使用权而应该处于等待状态; 只有当任务A把打印机释放后,系统才能唤醒任务B使其获得打印机的使用权。如果这两 个系统不这样做,那么也会造成严重的后果。

实验二、uCOS-II的多任务机制及其编程

实验二、μC/OS-II的多任务机制及其编程 一、实验目的 1、熟悉μC/OS-II任务的基本概念; 2、掌握μC/OS-II的多任务机制以及多任务应用程序编程的基本步骤; 3、了解μC/OS-II操作系统中多任务函数的源码基本结构; 4、在实验一的基础上进一步熟悉μC/OS-II应用程序的烧录步骤。 二、实验设备 2.1硬件 本实验采用的奋斗版STM32 MINI开发板,该硬件的详细说明参见实验一指导书。 2.2软件 Windows XP/Windows 7、RealView MDK、μC/OS-Ⅱ版本2.86 与移植包、ST 官方标准库V3.2 版、STM32? and STM8?Flash loader demonstrator,串口调试工具等。 三、实验内容 3.1 建立任务OSTaskCreate的使用 与实验一相同,本实验也是基于led_example_gui文件中的APP目录下的工程文件STM32-FD-ucgui.Uv2。在该项目中添加新文件app1.c,并在其中按下列要求编写代码。注意要将项目工程中app.c文件的main函数名字改掉,例如改为main1。该软件的主要功能是创建的任务,在任务中每隔20000个节拍的时间通过串口输出文字。源代码如下: /** 案例一演示OSTaskCreate 函数的使用方法*/ #include "includes.h" OS_STK Task1Stk[1024]; OS_STK Task2Stk[1024]; void Task1(void *pdata); void Task2(void *pdata); int main(int argc, char **argv)

uCOS2任务调度过程

(转)uCOS-II任务调度过程 ucos-II是基于任务优先级抢占式任务调度法的,就是内核在管理调度时,调用任务切换函数(一般为SSched()),在该函数中将此时已处于就绪状态(条件一)并且为最高优先级(条件二)的任务的保存于其栈中的相应信息压入cpu 寄存器中(软中断完成),然后cpu开始运行该任务的代码。 内核是何时进行任务调度的呢?虽然uC/OS-II是可被剥夺资源的内核(高优先级可强行占有低优先级正在使用的资源),但此事发生的前提是内核实时"检测"到了更高就绪的优先级了,那么内核是怎样来实时检测的呢? 带着这个问题让我们再来看看任务的结构——里边有函数 OSTimeDly(OS_TICKS_PER_SEC),一看就知道这是个延时函数,除了延时外它还会有其他用途呢?经查看其源码了解到里边有一条代码:OSSched(),对,函数OSTimeDly()的作用就是将此时正在运行的函数挂起(保存任务控制块OS_TCB中的相应信息)(任务控制块OS_TCB是系统分配给每个任务的信息存储单元),然后调用函数OSSched()进行任务切换,进而执行就绪的最高优先级任务。此刻,我们了解到uCOS-II的任务切换是在执行的任务中调用延时函数OSTimeDly()进行的。 现在,还有一个问题还没解决,就是当延时到了,内核如何将资源返还给被延时挂起的任务? 我们先来了解一下任务控制块(OS_TCB),任务控制块是一个数据结构,当任务的cpu使用权被剥夺时,uC/OS-II用它来保存该任务的状态。当任务重新得到cpu使用权时,任务控制块确保任务从当时被中断的那一点丝毫不差地继续执行。OS_TCB全部驻留在RAM中。在OS_TCB中有一项时间延时项OSTCBDly,调用函数OSTimeDly()过程中有一步骤就是给OSTCBDly赋延时值。uC/OS—II中有函数OSTimTick(),叫时钟节拍函数,它的一项工作就是给每个用户任务控制块OS_TCB中的时间延迟项OSTCBDly减1(如果该项不为零),当某项任务的任务控制块中的时间延时项OSTCBDly减为0时,这个任务就进入了就绪态,等待任务切换。而时钟节拍函数OSTimTick()的调用函数由时钟节拍中断服务函数OSTickISR()调用(或与相应函数配合调用)。现在,我们来理一下思路:任务调用函数OSTimeDly(),挂起任务和调用切换函数并设置延时时间——>周期性调用时钟节拍中断服务函数OSTickISR()进行任务延时计数(OSTimTick()完成),延时到时调用任务切换函数OSSched(),进行任务切换。 综上,任务切换有两种途径——时钟节拍中断服务函数OSTickISR()进行切换,任务中调用时间延迟函数OSTimeDly()进行切换。 从先后顺序来说,应该是OSTimeDly()先发生(设置OSTCBDly),才会有时钟节拍中断函数OSTickISR()进行切换的动作发生。

1.uCOS的任务控制块

进程控制块内容: typedef unsigned int OS_STK; /* ********************************************************************************************************* * TASK CONTROL BLOCK ********************************************************************************************************* */ typedef struct os_tcb { OS_STK *OSTCBStkPtr; /* 指向任务栈栈顶 */ #if OS_TASK_CREATE_EXT_EN > 0 void *OSTCBExtPtr; /* 指向任务可控制块扩展 */ OS_STK *OSTCBStkBottom; /* 指向任务栈栈底 */ INT32U OSTCBStkSize; /* 任务栈长度(堆栈中) */ INT16U OSTCBOpt; /* 通过OSTaskCreateExt()创建任务时的参数 */ INT16U OSTCBId; /* 任务id [0,65535] */ #endif struct os_tcb *OSTCBNext; /* 指向TCB链表中的下一个节点 */ struct os_tcb *OSTCBPrev; /* 指向TCB链表中的前一个节点 */ #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0) OS_EVENT *OSTCBEventPtr; /* 指向控制块 */ #endif #if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) void *OSTCBMsg; /* 指向由OSMboxPost()或OSQPost()传送的消息 */ #endif #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) #if OS_TASK_DEL_EN > 0 OS_FLAG_NODE *OSTCBFlagNode; /*指向事件标志节点 */ #endif OS_FLAGS OSTCBFlagsRdy; /* 事件标志,标志任务可以执行 */ #endif INT16U OSTCBDly; /* 任务等待的时间(节拍数) */ INT8U OSTCBStat; /* 任务当前状态 */ INT8U OSTCBPrio; /* 任务优先级 [0, 63] 0为最高级别 */ INT8U OSTCBX; /* OSRdyTbl[]的下标 [0,7] */ INT8U OSTCBY; /* OSRdyGrp的二进制数的位号 */ INT8U OSTCBBitX; /* 访问就绪表时用到的数据 */ INT8U OSTCBBitY; /* 访问就绪组时用到的数据 */ #if OS_TASK_DEL_EN > 0 BOOLEAN OSTCBDelReq; /* 请求删除任务时的标志 */ #endif } OS_TCB; OSTCBStat可用值:

ucos II 创建第一个任务之二

Ucos II 创建第一个任务之二 下面具体讲解下任务创建的过程 下图就是创建任务函数的实现程序。 INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio) { void *psp; INT8U err; if (prio > OS_LOWEST_PRIO) { (1) return (OS_PRIO_INVALID); } OS_ENTER_CRITICAL(); if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { (2) OSTCBPrioTbl[prio] = (OS_TCB *)1; (3) OS_EXIT_CRITICAL(); (4) psp = (void *)OSTaskStkInit(task, pdata, ptos, 0); (5) err = OSTCBInit(prio, psp, (void *)0, 0, 0, (void *)0, 0); (6) if (err == OS_NO_ERR) { (7) OS_ENTER_CRITICAL(); OSTaskCtr++; (8) OSTaskCreateHook(OSTCBPrioTbl[prio]); (9) OS_EXIT_CRITICAL(); if (OSRunning) { (10) OSSched(); (11) }

} else { OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0; (12) OS_EXIT_CRITICAL(); } return (err); } else { OS_EXIT_CRITICAL(); return (OS_PRIO_EXIST); } } 1.OSTaskCreate()一开始先检测分配给任务的优先级是否有效 [L4.1(1)]。任务的优先级必须在0到OS_LOWSEST_PRIO之间。 OS_LOWSEST_PRIO的定义是在os_cfg.h这个文件,定义如下: #define OS_LOWEST_PRIO 12 。这个地方mcu21就有些搞不懂,为什么不是64,而是12?有明白的可以告知mcu21同学。 2.接着,OSTaskCreate()要确保在规定的优先级上还没有建立任务 [L4.1(2)]。在使用μC/OS-Ⅱ时,每个任务都有特定的优先级。如果某个优先级是空闲未使用的,μC/OS-Ⅱ通过放置一个非空指针在OSTCBPrioTbl[]中来保留该优先级[L4.1(3)]。这就使得OSTaskCreate()在设置任务数据结构的其他部分时能重新允许中断[L4.1(4)]。 3.然后,OSTaskCreate()调用OSTaskStkInit()[L 4.1(5)],它负责建立任务的堆栈。没错,就是OSTaskStkInit(),系统移植时候,我们辛辛苦苦在OS_CPU_C.C编写了它,原来是跑到这里耀武扬威来了。OSTaskStkInit()

相关主题
文本预览
相关文档 最新文档