原理及应用2010嵌入式系统答案_第1页
原理及应用2010嵌入式系统答案_第2页
原理及应用2010嵌入式系统答案_第3页
原理及应用2010嵌入式系统答案_第4页
原理及应用2010嵌入式系统答案_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1.系统节拍:最小的时钟统节拍。就是两次中断之间相间隔的时间,这个最小时钟叫做系2.可型内核:CPU 总是运行多个任务中优先级别最高的那个任务,即使 CPU 正在运行某个低优先级的任务,当有高优先级别的任务准备就绪时,该高级别的任务就会正在运行任务的 CPU 使用权,而使内核。获得 CPU 的使用权,这样的内核叫做可型3.任务块:用来任务的堆栈指针,任务的当前状态,任务的优先级别等一些与任务管理有关的属性的表就叫做任务消息邮箱:在任务间传递数据时,需在块。器中建立一个数据缓冲区,把数据缓冲区的4.指针赋给块的成员 OSEventPrt,同时使块的成员 OSEventType 为常数OS_EVE

2、NT_TYPE_MBOX,则该块就叫做消息邮箱。5.优先级反转:在可型内核中,当任务以独占方式使用共享时,会出现低优先级任务先于高优先级任务而被运行的现象,这即所谓的任务优先级反转。互斥型信号量:互斥型信号量是一个二值信号量,任务可以用互斥型信号量来实现对共6.享的独占式处理。7.任务堆栈:在器中按数据“后进先出”的原则组织的连续空间,为了满足任务切换和响应中断时保存 CPU 寄存器中的内容及任务调用其他函数时的需要,每个任务都有的堆栈,即任务堆栈。8.任务调度:在多任务系统中,令 CPU 中止当前正在运行的任务转而去运行另一个任务的工作叫做任务切换,而按某种规则进行任务切换的工作叫做任务的调

3、度。9.可重入函数:函数能被多个任务所调用,并且这种能力的函数就叫做可重入函数。产生任务之间的互相干扰,凡是具有10. 队列:队列是一个有次序性的数据项目集合。其数据项目仅可由一端进入,而由另一端删除,这两端分别称为队尾和队头。队列具有“先进先出”的特性,称为 First-in-First-out, 简称 FIFO。二 1.(1)不支持时间片轮番调度法,应用程序中各任务的优先级必须互不相同。解决方法:一个任务的基础上增加一个基于时间片的微型调度核。(2) uCOS 支持动态优先级,即在任务的优先级可由用户改变,但在动态优先级的使用中易发生优先级反转问题。优先级反转问题的解决办法有优先级置顶和优

4、先级继承 2 种。a. 采用优先级置顶的方案,首先在创建互斥信号量时就应同时设置一个相应的置顶优先级,当首先申请到该的任务 a 未而又有一个更高优先级的任务 b 试图申请时, 内核会将任务 a 的优先级提升到置顶优先级,该置顶优先级高于任何可能申请该任务的高优先级。优先级置顶的意义在于使占有的低优先级任务尽快完成,让高优先级任务的等待不至过长,需要用到互斥信号量(Mutex)。b.优先级继承方案:即内核能自动变换任务的优先级。但是在C/OS-II 不支持优先级继承,可以通过修改操作系统的内核,使之成为可能。这里采用类似于时间片轮番调度法的方案,在同一优先级上对不同任务进行调度。给处于同一优先级

5、的不同任务都分配一个时间片,当内核运行到某一任务时,对同优先级且处于就绪态的任务依次进行调度,即当就绪态中先到的任务用完的时间片后,CPU任务。该任务用完的时间片后,CPU权转让给就绪态权又转让给后一个就绪态任务。当就绪态的每一个任务都被调度一次之后将重新为它们分配时间片,然后又开始新周期的调度。在调度过程中如果有一个比当前任务优先级更高的任务由其他态变成了就绪态(被创建或获取了一个信号量等等),当前任务的CPU用权。权将被;空闲任务仍然是等到其他任务都就绪态才获得CPU 使2uCOS 如何实现时间管理,如何在系统节拍之外使用 CPU 的硬件定时器?(1)uc/os-ii 的时间管理是通过定时

6、中断来实现的,该定时中断一般为 10ms 或 100ms 发生一次,时间频率取决于用户对硬件系统的定时器编程来实现中断发生的时间间隔是固定不变的,该中断也称为一个时钟节拍。uc/os-ii 的时钟节拍服务是通过在中断服务子程序中调用 OSTimeTick()实现的。OSTimeTick()跟踪所有任务的定时器及超时时限。uc/os-ii 用于时间管理的函数有:1) 任务延时函数,OSTimeDly() :2) 按时、分、秒延时函数,OSTimeDlyHMSM(): 3)恢复延时的任务,OSTimeDlyResume(): 4)系统时间,OSTimeGet()和 OSTimeSet():(2)硬

7、件定时器以时钟节拍为周期定时地产生中断,该中断的中断服务程序叫做OSTickISR(),中断服务程序通过调用时钟节拍服务函数OSTimeTick()来完成系统在每个时钟节拍时需要做的工作。3.任务就绪表登记了系统中所有处于就绪状态的任务,任务调度器在确认未被上锁并且不是中断服务程序调用调度器的情况下,首先从任务就绪表中查的的最高优先级别就绪任务的优先级别,然后再确认了这个就绪任务不是当前正在运行的任务的条件下,用 OSPrioHighRdy作为下标去数组 OSTCBPrioTb1,把数组元素 OSTCBPrioTb1OSPrioHighRdy的值赋给指针变量 OSTCBHighRdy。于是下面

8、就可以依据 OSTCBHighRdy 和 OSTCBCur 这两个分块的指针在宏 OS_TASK_SW()中实施任务切换别指向待运行任务块和当前任务了。OS_TASK_SW()完成的工作依次如下:(1) 把被中止任务的断点指针保存到任务堆栈中;(2) 把 CPU 通用寄存器的内容保存到任务堆栈中;(3) 把被中止任务的任务堆栈指针当前值保存到该任务的任务块的 OSTCBStkPtr 中;(4)获得待运行任务的人为块;(5)使 CPU 通过任务块获得待运行任务的任务堆栈指针;(6) 把待运行任务堆栈中通用寄存器的内容恢复到 CPU 的通用寄存器中;(7) 使 CPU 获得待运行任务的断点指针。4

9、结合MagicARM2200 提供的 lcddriver 的功能,说明 RTOS 中设备驱动引擎的作用以及使用方法。作用:设备驱动程序是物理设备和操作系统之间的软件接口,它由一组子程序组成,它负责与物理设备通讯,并为操作系统的提供统一的接口。用户级的程序通过设备文件来设备,但实际设备的读写则由设备驱动程序完成。对硬件的驱动,有两种方式:直接加载到内核代码中,启动内核时就会驱动此硬件设备。另一种是以模块方式,编译生成一个的文件。当应用程序需要加载进内核空间运行。我们所说的一个硬件的驱动程序,通常指的是一个驱动模块。使用方法:MagicARM2200 的驱动程序均以模块的形式提供,可以进行动态加载

10、或者卸载。在运行使用了驱动程序的应用程序之前,需先加载相应的驱动程序,通过 insmod 命令实现。在使用过程中,可使用通过 ismod 查看已经加载的设备,若想卸载某个模块,使用通过 immod 命令对模块进行动态卸载。在运行用户程序之前,需完成的准备工作有:创建设备节点,加载驱动程序,如果都通过输入命令进行,比较繁琐,而且容易出错。为了简化操作,可以把这些命令写成一个文件,直接运行该文件即可。5.uCOS 对内存进行两级管理,即把续的内存空间分为若干个分区,每个分区又分为若干个大小相等的内存块。操作系统以分区为来管理动态内存,而任务以内存块为来获得和动态内存。内存分区及内存块的使用情况则由

11、内存块来。两者的关系是内存分区是由大小相等的多个内存块组成的,每个分区内的内存块至少有两块,每个内存块的空间至少能存放一个指针,因为要在内存块中建立一个用于把分区内的内存块个链表的指针。为一6.为了使系统能够感知和有效地管理内存分区,uCOS 定义了一个叫做内存块的数据结构,该数据结构的内存分区指针 OSMemAddr 指向了内存分区,内存分区中的各个内存块又组成了一个单向链表,内存块的链表指针 OSMemFreeList 就指向了这个单向链表的头。7.信号量广泛地应用于任务间的同步工作中,使用信号量的目的是为了给共享设立一个标志,该标志表示该共享被占用情况。这样,当一个任务在共享之前,就可以

12、先对这个标志进行,从而在了解被占用的情况之后,再来决定的行为;信号量集自荷兰学者提出后广泛地使用在同步工作和互斥工作环境的机理中。比如,在分析任务时发现两段程序要同步完成,那么可以使用信号量集的办法。一个进程完成后,给出完成的信号,另一个信号也完成时同时给出另一个信号量,当最后的一个进程所需要的所有信号量都正确时,才开始执行。前边的所有进程是同步完成的,也可以这样理解,一个进程完成到某一个阶段后阻塞等待另一个进程的信号量,另一个进程给出信号量,则等待信号的进程可以继续进行,最终完成这种同步的工作。两个进程同时抢点某一类时,先给出信号量,用信号时表示这种(称之为临界)的数量。当数量不足时,等待另

13、一个进程后获得。这样完成了互斥进程的调动。三 设计实例:1.结合下面的系统框图,说明 MiniGUI 如何在 uCOS 环境下运行,详细描述移植的步骤。键盘器件是移植了 uCOS 的 ARM7,外设有 I2C 接口的键盘、LED 驱动上图的ZLG7290 和数码管;界面显示模块:LCD 驱动和 LCD 显示屏。MiniGUI 的使用:要在目标板上运行 MiniGUI for uc/os-ii 应用程序,首先要使用缩主机(即PC 机)对 MiniGUI 的源代码进行编译(交叉编译),生成 MiniGUI 静态文件(如MiniGUI-Lib.a)。然后 MiniGUI 应用程序也在缩主机上进行交叉

14、编译,并且与 MiniGUI 静态库、POSIX 线程库生成*.axf 映像文件或*.bin 二进制文件。最后,将 MiniGU(I *.axfZLG 7290ARM7With uCOSLCDPanelLCD DriverS1D13503数码管映像文件或*.bin 二进制文件)应用程序到目标板,并运行。移植:MiniGUI 有图形抽象层(GAL)和输入抽象层(IAL),它定义了一组不依赖与任何特殊硬件的抽象接口,所有顶层的图形操作和输入处理都建立在抽象接口之上,而实现这一抽象接口的底层代码称为“图形引擎”和“输入引擎”。(1) MiniGUI 的 GAL 的移植MiniGUI-STR 不支持

15、newgal 功能,所以需要按照老的 GAL 接口来编写适合于MagicARM2200 的图形引擎。首先,在MiniGUI-Liblibminigui-str-1.6.2-ucosiisrcgalnative 目录下的 commlcd.c 文件中编写老的 GAL 接口的几个接口函数。然后,在 MiniGUI-Liblibminigui-str-1.6.2-ucosiisrcgalnative 目录建立液晶驱动程序文件 lcddrive.c 和 lcddrive.h,液晶驱动程序是根据液晶模块和硬件连接电路来设计的。由于在 lcddrive.c 文件中使用了 LPC2294 的头文件 lpc22

16、94.h,所以要将此文件到此目录下。(2) MiniGUI 的 IAL 的移植MiniGUI 通过 INPUT 数据结构来表示输入引擎, 此数据结构的定义是在MiniGUI-Liblibminigui-str-1.6.2-ucosiisrcincludeial.h文 件 中 。 首 先 , 在MiniGUI-Liblibminigui-str-1.6.2-ucosiisrcial 目录下 comminput.c 文件中编写 IAL 接口的几个接口函数。然后,在 MiniGUI-Liblibminigui-str-1.6.2-ucosiisrcial 目录建立键盘驱动程序文件comm-drive

17、.c,实现触摸屏、键盘输入以及键码转换。2.在 51 系列单片机上移植 uCOS 时需要修改的主要是以下几个方面:(1)文件 OS_CPU.H 的修改a. 堆栈的增长方向:由于 51 单片机规定堆栈从低地址向高地址增长,所以用来定义堆栈增长方向的常数 OS_STK_GROWTH 的值应该为 1 即#define OS_STK_GROWTH 1。b. 定义临界段的宏:设置临界区的两个宏分别直接使用 51 单片机的开中断和关中断指令来实现 即 #define OS_ENTER_CRITICAL() EA=0; #define OS_EXIT_CRITICAL() EA=1。c. 定义任务切换宏:任

18、务切换由汇编语言编写的函数 OSCtxSw()来实现,任务切换宏OS_TASK_SW()封装了对任务切换函数 OSCtxSw()的调用。即 #define OS_TASK_SW()OSCtxSw()。d. 定义数据类型:如 typedef unsighed char BOOLEAN;typedef unsigned char INT8U;typedef signed char INT8S; typedef unsigned int INT16U; typedef signed int INT16S 等,另外还有typedef unsigned char OS_STK。(2)任务堆栈的设计51

19、单片机在任务切换时要进行任务堆栈和系统堆栈之间的操作,所以为了方便工作,应该在堆栈中存有堆栈长度的数据。在 51 单片机的外部 RAM 中设置任务堆栈映像,任务堆栈映像的最低地址空间用来存放用户堆栈的长度, 并使该任务的 TCB 中的OSTCBStrPtr 指针变量指向该地址。51 单片机的堆栈指针 SP 总是先加 1 再存数据,因此,SP 初始时指堆栈起始地址减 1 处。在任务切换时,应该先把当前任务在系统堆栈的内容保存到该任务堆栈映像中,然后把就绪最高优先级任务堆栈映像中的内容到系统堆栈。(3) 文件 OS_CPU_C.C 的修改该文件需要修改的内容主要为任务堆栈初始化函数 OSTaskS

20、tkInit()。由于要使用单片机的定时器设置时钟中断,因此还要添加对 51 单片机定时器的初始化程序。另外需要几点注意事项,因为在默认情况下 KEIL 编译器生成的代码不可重入,如果要生成可重入代码,则必须在函数后面显式地使用关键字 reentrant。另外,由于 uCOS 使用的pdata,data 等参数都与 KEIL 的关键字相同,所以还要把这些数据改成 ppdata,ddata 等。在uCOS 汇编源程序用到了 OSTCBCur,OSTCBHighRdy 等变量,为了使用 Ri 而不用 DPTR 对它们进行,要使用 KEIL 扩展关键字 IDATA,将它们定义在内部 RAM 中。3

21、设置 3 个任务,每个任务通过 STM32F103 的串口输出一串字符串答:首先程序开始,进行初始化,初始化包括时钟初始化、中断初始化、IO 接口初始化、串口初始化等。主程序完成这些初始化后创建信号量,消息邮箱和任务创建。#include"stm32f10x_lib.h"#include“config.h”OS_EVENT OS_EVENT OS_EVENT*APP_UserIFSem;*APP_UserIFSeml;*APP_UserIFMbox;void void voidTask1(void Task2(void Task3(void*data)*data)*data

22、)512;512;512;reentrant; reentrant; reentrant;#define #define #define OS_STK OS_STK OS_STKOS_Task1 OS_Task2 OS_Task3Task1StkOS_Task1; Task2StkOS_Task2; Task3StkOS_Task3;void void void voidRCC_Configuration(void); GPIO_Configuration(void); NVIC_Configuration(void); UART_Configuration(void);void main(v

23、oid)OSInit(); UART_configuration(); RCC_Configuration;GPIO_Configuration;NVIC_Configuration; OSTaskCreate(Task1,(void*)0,&Task1Stk0,2); OSTaskCreate(Task2,(void*)0,&Task1Stk0,3); OSTaskCreate(Task3,(void*)0,&Task1Stk0,4);OSStart();void App_EventCreat(void)App_ UserIFSem = OSSemCreate(0);

24、App_ UserIFSeml = OSSemCreate(0);App_ UserIFMbox = OSMboxCreate((void*)0);void Task1(void * data) reentrantdata = data;printf(“Hello! The world.”) for(;)Printf(“tttThis is Task1.n”); OSTimeDly(OS_TICKS_PER_SEC);void Task1(void * data) reentrantdata = data; for(;)Printf(“tttThis is Task2.n”); OSTimeD

25、ly(3*OS_TICKS_PER_SEC);void Task1(void * data) reentrantdata = data; for(;)Printf(“tttThis is Task3.n”); OSTimeDly(6*OS_TICKS_PER_SEC);/* *UART.H*/ #include”stm32f10x_lib.h”#ifndef_DRIVE_UART_H #define_DRIVE_UART_H#ifdef _UART_C#define #else #define#endifEXT_UARTEXT_UART extern#define Rxbuffersize 0

26、x01 #define PORT_MAX2#define COM1 0#define COM2 1#define COM3 2#define COM4 3#define OPEN 1#define CLOSED 0void UART_configuration(void); void printf(char *format,);EXT_UART UINT8 open_port (UINT8 port,UINT32 baud,UINT8 startbit,UINT8 databit,UINT8 stopbit,UINT8 parity);EXT_UART void closeUart(UINT8

27、 num);EXT_UART UINT8 send_data(UINT8 port,UINT8 *pdata,UINT8 length); EXT_UART UINT8 send_str(UINT8 port,UINT8 *pstr);/*UART.c*/#inlcude “config.h” #include “uart.h” #define _UART_C#define RECE_BUF_LEN 256#define SEND_BUF_LEN 256 Typedef structUINT8 send_bufferSEND_BUF_LEN; UINT8 race_bufferRECE_BUF

28、_LEN; UINT8 send_head;UINT8 send_end; UINT8 race_head; UINT8 rece_end; UINT8 state;UINT8 transmiting_flag;PORT;PORT comPORT_MAX;typedef char *uart_va_list;#define uart_sizeof_int(n) #define uart_va_start(ap,v) #define uart_va_arg(ap,t)#define uart_va_end(ap)(sizeof(n)+sizeof(int)-1)&(sizeof(int)

29、-1) (ap = (uart_va_list)&v+uart-sizeof_int(v)(*(t*)(ap+=uart_sizeof_int(t)-uart_sizeof_int(t)(ap = (uart_va_list)0)#define UART_SEND_BYTE(ch) USART_Send char(USART1,(u8*)ch)extern u8 write_data(u8 port); void UART_configuration(void)USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART

30、_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = US

31、ART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);void USART_sendchar(USART_TypeDef *USARTx,u8*Data)USARTx->DR = (Data0&(u16)0x01FF);while(USART_GetFlagStatus(USART_FLAG_TXE) = RESET);UINT8open_port(UINT8port,UINT32baud,UINT8startbit,UINT8datab

32、it,UINT8stopbit,UINT8 patity)if(port>(PORT_MAX-1)|(baud>230400)|(databit>8)return FALSE ;If(comport.state = TRUE)return FALSE; OS_ENTER_ CRITICAL();comport.send_head = 0 ; comport.send_end = 0 ;comport.race_head = 0 ; comport.race_end = 0 ; comport.transmiting_flag = FALSE ; if(port = = COM

33、1)else if(port = = COM2 ) comport.state = OPEN; OS_EXIT_CRITICAL();return TRUE;UINT send_data(UINT8 pirt,UINT8 *pdata,UINT8 length)UINT8 I;if(port>PORT_MAX)return 0;if(comport.state = close)|(length = 0)return 0; OS_ENTER_CRITICAL();for(i=0;i<length;i+)comport.send_buffer(comport.send_head+) =

34、 pdatai; if(comport.send_head = = comport.send_end)comport.send_end+;write_data(0); OS_EXTI_CRITICAL();return i;UINT8 send_str(UINT8 port,UINT8 *pstr)UINT8 i=0 ; OS_EMTER_CRITICAL() ;while (pstri+!=0); OS_EXTI_CRITICAL();return(send_data(port,pstr,i-1);UINT8 write_data(UINT8 port)if(comport.send_hea

35、d = = comport.send_end)USART_ITConfig(USART1,USART_IT_TC,DISABLE);return FALSE; USART_ITCONfig(USART1,USART_IT_TC,ENABLE); OS_ENTER_CRITICAL();if(port = = COM1)USART_sendData(USART1,comport.send_buffer(comport.send_end+);else if(port = = COM2) if(comport.send_end = = comport.send_head ) OS_EXTI_CRIT

36、ICAL();return TRUE;等待消息邮箱五、模块与结果:消息邮箱数据显示信号量APP userIFasm系统启动任务创建串口数据任务任务二显示任务三显示任务一显示邮箱信号量创建初始化开始AT90S8535 单片机与 DAC0808Figure 2单片机与0808 进行 D/A 转换,DAC0808 是具有 16 个引脚的双列直插式8 位 D/A 转换器件。其引脚功能分别为:1 脚为空,2 脚为 GND,3 脚为 VEE,4 脚为 DAC 输出引脚,512 脚为数据输入引脚,13 脚为 VCC,14 脚为基准电压(VREF),15 脚为基准电压(VREF),16 脚为 COMPENSA

37、TION。当数据输入量全为 0时,其 4 脚输出电压最低,接近零;当数据输入量全为 1 时,其 4 脚输出电压最高,电压值由基准电压 VREF 决定。代码:#define _dac_c#include<io8535v.h>#include<macros.h>#include<dac.h>#define debug_p (*(volatileuint*)0xa0)void dac_init (void)vol_data = 0;TIMSK = 0x04;TCCR1B = 0x00; /stopTCNT1H = 0xf5; /setupTCNT1L = 0xEE;OCR1AH = 0x7A;OCR1AL = 0x12;OCR1BH = 0x7A;OCR1BL = 0x12;TCCR1A = 0x00;TCCR1B = 0x02; /start Timervoid put_to_dac (void)TCNT1H = 0xf5; /setupTCNT1L = 0xEE;data_port = sin_tabelvol_data;vol_data+;debug_p= vol_data;if (vol_data>20) vol_data =0;由 DAC0808输出正弦波电流,通过图 Fig

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论