uc编译器
① uc/os iii应该使用什么编译器
找到适合你的arm板的编译器(常用的有ADS、Keilforarm(也就是keilMDK)、IAR等),将uc/os源码进行编译,前提是这里的源代码已经经过移植,可以在你的arm上运行,也就是us/os官方所谓的“port”。然后,一般通过jlink或Ulink下载到电路板,如果你的电路板有类似于bootloader之类的启动代码,一般还可以用串口或网线或USB下载
② UC,C,C++,VC,C#,.NET的区别与联系,简单说下。谢谢!
UC 好像是手机浏览器吧。
C 是一种面向过程的语言。
C++ 是一种面向对象的编程语言。
VC是C ,C++ 程序的编辑软件。
C# 是一种面向对象的编程语言。
.NET 是一个开发平台。
③ 嵌入式实时操作系统uc/uo-II在ARM上的移植 这个设计有做过吗,给点线索 非常感谢
所谓移植,就是使一个实时内核能在某个微处理器或微控制器上运行。为了方便移植,大部分的µC/OS-Ⅱ代码是用c语言写的;但仍需要用C和汇编语言写一些与处理器相关的代码,这是因为µC/OS-Ⅱ在读写处理器寄存器时只能通过汇编语言来实现。由于µC/OS-Ⅱ在设计时就已经充分考虑了可移植性,所以µC/OS-Ⅱ的移植相对来说是比较容易的。[5,6]
要使µC/OS-Ⅱ正常运行,处理器必须满足以下要求:
(1) 处理器的C编译器能产生可重入代码。
(2) 用C语言就可以打开和关闭中断。
(3) 处理器支持中断,并且能产生定时中断(通常在10至100Hz之间)。
(4) 处理器支持能够容纳一定量数据(可能是几千字节)的硬件堆栈。
(5) 处理器有将堆栈指针和其它CPU寄存器读出和存储的指令
图2-1说明了µC/OS-Ⅱ的结构以及它与硬件的关系。从图中可以看到整个系统的架构。最底层是硬件层,该层主要涉及到CPU处理器的架设,以及它与外部各功能模块的连接,对于CPU处理器的初始化也是构架嵌入式系统的重要内容,特别是对定时器的设置,将是构建操作系统的基础,它决定整个系统的性能。对于软件部分,最底层是与处理器相关的程序代码,该段代码直接对CPU处理器进行初始化,这部分代码就是移植操作系统的主要内容,也是最难以理解的部分。这段代码绝大部分程序是用汇编语言编写的,因为在程序运行的时候,这部分代码的调用次数最频繁。在向上的代码就与处理器没有任何的关系,其中一部分包括操作系统的配置文件,像OS_CORE.c,OS_FLAG.c等文件。这部分代码是用来编写一些基本的底层函数,这些函数将作为以后应用部分的基本函数库进行调用,这部分函数构成了操作系统的基本构架,不同的操作系统所对应的系统的设计思想不同,主要体现在这些函数的设计中。除了系统的基本函数外,还有应用部分的基本配置文件。该文件声明的是与具体的应用配置有关的一些设置文件。比如,各任务的一些基本参数,所使用的信号量的声明,以及液晶的参数配置等。不同的应用程序对应的该文件参数配置也不同。有了底层的基本配置文件,就可以编写具体的应用程序了,最上层就是应用程序,针对不同的应用需求,编写不同的应用程序。
μCOS-II不使用C语言中的short、int、long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。代之以移植性强的整数数据类型,这样,既直观又可移植,不过这就成了必须移植的代码。根据ADS编译器的特性,这些代码如程序清单图2-2所示。
与所有的实时内核一样,µC/OS-Ⅱ需要先禁止中断再访问代码的临界段,并且在访问完毕后重新允许中断。这就使得µC/OS-Ⅱ能够保护临界段代码免受多任务或中断服务例程(ISRs)的破坏。为了隐藏编译器厂商提供的具体实现方法,µC/OS-Ⅱ定义了两个宏来禁止和允许中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。
μCOS-II使用结构常量OS_STK_GROWTH中指定堆栈的生长方式:置OS_STK_GROWTH为0表示堆栈从下往上长。置OS_STK_GROWTH为1表示堆栈从上往下长。虽然ARM处理器核对于两种方式均支持,但ADS的C语言编译器仅支持一种方式,即从上往下长,并且必须是满递减堆栈,所以OS_STK_GROWTH的值为1。
µC/OS-Ⅱ的移植实例要求用户编写四个简单的汇编语言函数: OSStartHighRdy();OSCtxSw();OSIntCtxSw();OSTickISR()。如果用户的编译器支持插入汇编语言代码的话,用户就可以将所有与处理器相关的代码放到OS_CPU_C.C文件中,而不必再拥有一些分散的汇编语言文件。
使就绪状态的任务开始运行的函数叫做OSStart(),如下示意函数所示。在用户调用OSStart()之前,用户必须至少已经建立了一个任务。OSStartHighRdy()假设OSTCBHighRdy指向的是优先级最高的任务的任务控制块。为了简单一点,堆栈指针总是储存在任务控制块(即它的OS_TCB)的开头。换句话说,也就是要想恢复的任务堆栈指针总是储存在OS_TCB的0偏址内存单元中。
如果当前任务调用µC/OS-Ⅱ提供的系统服务,并使得更高优先级任务处于就绪状态,µC/OS-Ⅱ就会借助上面提到的向量地址找到OSCtxSw()。在系统服务调用的最后,µC/OS-Ⅱ会调用OSSched(),并由此来推断当前任务不再是要运行的最重要的任务了。软中断 (或陷阱) 指令会强制一些处理器寄存器(比如返回地址和处理器状态字)到当前任务的堆栈中,并使处理器执行OSCtxSw()。这些代码必须写在汇编语言中,因为用户不能直接从C中访问CPU寄存器。注意在OSCtxSw()和用户定义的函数OSTaskSwHook()的执行过程中,中断是禁止的。
OSIntExit()通过调用OSIntCtxSw()来从ISR中执行切换功能。因为OSIntCtxSw()是在ISR中被调用的,所以可以断定所有的处理器寄存器都被正确地保存到了被中断的任务的堆栈之中。实际上除了需要的东西外,堆栈结构中还有其它的一些东西。OSIntCtxSw()必须要清理堆栈,这样被中断的任务的堆栈结构内容才能满足人们的需要。
要想了解OSIntCtxSw(),大家可以看看µC/OS-Ⅱ调用该函数的过程。假定中断不能嵌套(即ISR不会被中断),中断是允许的,并且处理器正在执行任务级的代码。当中断来临的时候,处理器会结束当前的指令,识别中断并且初始化中断处理过程,包括将处理器的状态寄存器和返回被中断的任务的地址保存到堆栈中。至于究竟哪些寄存器保存到了堆栈上,以及保存的顺序是怎样的,并不重要。
接着,CPU会调用正确的ISR。µC/OS-Ⅱ要求ISR在开始时要保存剩下的处理器寄存器。一旦寄存器保存好了,µC/OS-Ⅱ就要求或者调用OSIntEnter(),或者将变量OSIntNesting加1。在这个时候,被中断任务的堆栈中只包含了被中断任务的寄存器内容。现在,ISR可以执行中断服务了。并且如果ISR发消息给任务(通过调用OSMboxPost()或OSQPost()),恢复任务(通过调用OSTaskResume()),或者调用OSTimeTick()或OSTimeDlyResume()的话,有可能使更高优先级的任务处于就绪状态。
假设有一个更高优先级的任务处于就绪状态。µC/OS-Ⅱ要求用户的ISR在完成中断服务的时候调用OSIntExit()。OSIntExit()会告诉µC/OS-Ⅱ到了返回任务级代码的时间了。调用OSIntExit()会导致调用者的返回地址被保存到被中断的任务的堆栈中。
OSIntExit()刚开始时会禁止中断,因为它需要执行临界段的代码。根据OS_ENTER_CRITICAL()的不同执行过程,处理器的状态寄存器会被保存到被中断的任务的堆栈中。OSIntExit()注意到由于有更高优先级的任务处于就绪状态,被中断的任务已经不再是要继续执行的任务了。在这种情况下,指针OSTCBHighRdy会被指向新任务的OS_TCB,并且OSIntExit()会调用OSIntCtxSw()来执行任务切换。调用OSIntCtxSw()也同样使返回地址被保存到被中断的任务的堆栈中。
用户切换任务的时候,用户只想将某些项保留在堆栈中,并忽略其它项。这是通过调整堆栈指针(加一个数在堆栈指针上)来完成的。加在堆栈指针上的数必须是明确的,而这个数主要依赖于移植的目标处理器(地址空间可能是16,32或64位),所用的编译器,编译器选项,内存模式等等。另外,处理器状态字可能是8,16,32甚至64位宽,并且OSIntExit()可能会分配局部变量。有些处理器允许用户直接增加常量到堆栈指针中,而有些则不允许。在后一种情况下,可以通过简单的执行一定数量的pop(出栈)指令来实现相同的功能。一旦堆栈指针完成调整,新的堆栈指针会被保存到被切换出去的任务的OS_TCB中。
这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。如果用户的编译器支持插入汇编语言代码的话,用户就可以将OSIntCtxSw()代码放到OS_CPU_C.C文件中,而不放到OS_CPU_A.ASM文件中。正如用户所看到的那样,除了第一行以外,OSIntCtxSw()的代码与OSCtxSw()是一样的。这样在移植实例中,用户可以通过“跳转”到OSCtxSw()中来减少OSIntCtxSw()代码量。
µC/OS-Ⅱ要求用户提供一个时钟资源来实现时间的延时和期满功能。时钟节拍应该每秒钟发生10-100次。为了完成该任务,可以使用硬件时钟,也可以从交流电中获得50/60Hz的时钟频率。
这些代码必须写在汇编语言中,因为用户不能直接从C语言中访问CPU寄存器。如果用户的处理器可以通过单条指令来增加OSIntNesting,那么用户就没必要调用OSIntEnter()了。增加OSIntNesting要比通过函数调用和返回快得多。OSIntEnter()只增加OSIntNesting,并且作为临界段代码中受到保护。
µC/OS-Ⅱ的移植实例要求用户编写六个简单的C函数:OSTaskStkInit(); OSTaskCreateHook();OSTaskDelHook();OSTaskSwHook();OSTaskStatHook(); OSTimeTickHook()。唯一必要的函数是OSTaskStkInit(),其它五个函数必须得声明但没必要包含代码。
OSTaskCreate()和OSTaskCreateExt()通过调用OSTaskStkInt()来初始化任务的堆栈结构,因此,堆栈看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。显示了OSTaskStkInt()放到正被建立的任务堆栈中的东西。注意,在这里我假定了堆栈是从上往下长的。下面的讨论同样适用于从下往上长的堆栈。
在用户建立任务的时候,用户会传递任务的地址,pdata指针,任务的堆栈栈顶和任务的优先级给OSTaskCreate()和OSTaskCreateExt()。虽然OSTaskCreateExt()还要求有其它的参数,但这些参数在讨论OSTaskStkInt()的时候是无关紧要的。为了正确初始化堆栈结构,OSTaskStkInt()只要求刚才提到的前三个参数和一个附加的选项,这个选项只能在OSTaskCreateExt()中得到。
该函数主要是对相关的几个寄存器进行初始化工作,初始化的寄存器对应于
④ UC浏览器电脑版禁用java的功能在哪里设置
浏览器禁止了java功能
可以根据下面操作打开它。A.打开IE,选择“工具”-“Internet选项”-“高级”-“JAVA VM”下的第一个选项“启用JavaJIT编译器”。(有些浏览器版本没有这一项,可以不管它。)B.打开IE打开“工具”-“Internet选项”-“安全”-“自定义级别...”对话框,(1).把“Microsoft VM”中的java权限设置为“安全等级-中”,(2)把“脚本”中的“java小程序脚本”设置为“启用”和“活动脚本”设置为“启用”。完成上面操作后,您需要把你的浏览器关掉再重新打开一下。
⑤ uc/os操作系统是怎样启动的
uc/os和uclinux操作系统是两种性能优良源码公开且被广泛应用的的免费嵌入
式操作系统,可以作为研究实时操作系统和非实时操作系统的典范。本文通过对
uc/os和uclinux的对比,分析和总结了嵌入式操作系统应用中的若干重要问题,
归纳了嵌入式系统开发中操作系统的选型依据。
两种开源嵌入式操作系统介绍
uc/os和uclinux操作系统,是当前得到广泛应用的两种免费且公开源码的嵌入
式操作系统。uc/os适合小型控制系统,具有执行效率高、占用空间小、实时性
能优良和可扩展性强等特点,最小内核可编译至2k。uclinux则是继承标准linux
的优良特性,针对嵌入式处理器的特点设计的一种操作系统,具有内嵌网络协议、
支持多种文件系统,开发者可利用标准linux先验知识等优势。其编译后目标文
件可控制在几百k量级。
uc/os是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。
其内核提供任务调度与管理、时间管理、任务间同步与通信、内存管理和中断服
务等功能。
uclinux是一种优秀的嵌入式linux版本。uclinux是micro-conrol-linux的缩写。
同标准linux相比,它集成了标准linux操作系统的稳定性、强大网络功能和出
色的文件系统等主要优点。但是由于没有mmu(内存管理单元),其多任务的实
现需要一定技巧。
两种嵌入式操作系统主要性能比较
嵌入式操作系统是嵌入式系统软硬件资源的控制中心,它以尽量合理的有效方法
组织多个用户共享嵌入式系统的各种资源。其中用户指的是系统程序之上的所有
软件。所谓合理有效的方法,指的就是操作系统如何协调并充分利用硬件资源来
实现多任务。复杂的操作系统都支持文件系统,方便组织文件并易于对其规范化
操作。
嵌入式操作系统还有一个特点就是针对不同的平台,系统不是直接可用的,一般
需要经过针对专门平台的移植操作系统才能正常工作。
进程调度、文件系统支持和系统移植是在嵌入式操作系统实际应用中最常见的问
题,下文就从这几个角度入手对uc/os和uclinux进行分析比较。
进程调度
任务调度主要是协调任务对计算机系统内资源(如内存、i/o设备、cpu)的争夺
使用。进程调度又称为cpu调度,其根本任务是按照某种原则为处于就绪状态
的进程分配cpu。由于嵌入式系统中内存和i/o设备一般都和cpu同时归属于
某进程,所以任务调度和进程调度概念相近,很多场合不加区分,下文中提到的
任务其实就是进程的概念。
进程调度可分为"剥夺型调度"和"非剥夺型调度"两种基本方式。所谓"非剥夺型
调度"是指:一旦某个进程被调度执行,则该进程一直执行下去直至该进程结束,
或由于某种原因自行放弃cpu进入等待状态,才将cpu重新分配给其他进程。
所谓"剥夺型调度"是指:一旦就绪状态中出现优先权更高的进程,或者运行的进
程已用满了规定的时间片时,便立即剥夺当前进程的运行(将其放回就绪状态),
把cpu分配给其他进程。
作为实时操作系统,uc/os是采用的可剥夺型实时多任务内核。可剥夺型的实时
内核在任何时候都运行就绪了的最高优先级的任务。uc/os中最多可以支持64
个任务,分别对应优先级0"63,其中0为最高优先级。调度工作的内容可以分
为两部分:最高优先级任务的寻找和任务切换。
其最高优先级任务的寻找是通过建立就绪任务表来实现的。uc/os中的每一个任
务都有独立的堆栈空间,并有一个称为任务控制块tcb(task control block)数据
结构,其中第一个成员变量就是保存的任务堆栈指针。任务调度模块首先用变量
ostcbhighrdy记录当前最高级就绪任务的tcb地址,然后调用os_task_sw()
函数来进行任务切换。
uclinux的进程调度沿用了linux的传统,系统每隔一定时间挂起进程,同时系
统产生快速和周期性的时钟计时中断,并通过调度函数(定时器处理函数)决定进
程什么时候拥有它的时间片。然后进行相关进程切换,这是通过父进程调用fork
函数生成子进程来实现的。
uclinux系统fork调用完成后,要么子进程代替父进程执行(此时父进程已经
sleep),直到子进程调用exit退出;要么调用exec执行一个新的进程,这个时候
产生可执行文件的加载,即使这个进程只是父进程的拷贝,这个过程也不可避免。
当子进程执行exit或exec后,子进程使用wakeup把父进程唤醒,使父进程继续
往下执行。
uclinux由于没有mmu管理存储器,其对内存的访问是直接的,所有程序中访
问的地址都是实际的物理地址。操作系统队内存空间没有保护,各个进程实际上
共享一个运行空间。这就需要实现多进程时进行数据保护,也导致了用户程序使
用的空间可能占用到系统内核空间,这些问题在编程时都需要多加注意,否则容
易导致系统崩溃。
由上述分析可以得知,uc/os内核是针对实时系统的要求设计实现的,相对简单,
可以满足较高的实时性要求。而uclinux则在结构上继承了标准linux的多任务
实现方式,仅针对嵌入式处理器特点进行改良。其要实现实时性效果则需要使系
统在实时内核的控制下运行,rt-linux就是可以实现这一个功能的一种实时内
核。
文件系统
所谓文件系统是指负责存取和管理文件信息的机构,也可以说是负责文件的建
立、撤销、组织、读写、修改、复制及对文件管理所需要的资源(如目录表、存
储介质等)实施管理的软件部分。
uc/os是面向中小型嵌入式系统的,如果包含全部功能(信号量、消息邮箱、消
息队列及相关函数),编译后的uc/os内核仅有6"10kb,所以系统本身并没有
对文件系统的支持。但是uc/os具有良好的扩展性能,如果需要的话也可自行
加入文件系统的内容。
uclinux则是继承了linux完善的文件系统性能。其采用的是romfs文件系统,
这种文件系统相对于一般的ext2文件系统要求更少的空间。空间的节约来自于
两个方面,首先内核支持romfs文件系统比支持ext2文件系统需要更少的代码,
其次romfs文件系统相对简单,在建立文件系统超级块(superblock)需要更少的存
储空间。romfs文件系统不支持动态擦写保存,对于系统需要动态保存的数据采
用虚拟ram盘的方法进行处理(ram盘将采用ext2文件系统)。
uclinux还继承了linux网络操作系统的优势,可以很方便的支持网络文件系统
且内嵌tcp/ip协议,这为uclinux开发网络接入设备提供了便利。
由两种操作系统对文件系统的支持可知,在复杂的需要较多文件处理的嵌入式系
统中uclinux是一个不错的选择。而uc/os则主要适合一些控制系统。
操作系统的移植
嵌入式操作系统移植的目的是指使操作系统能在某个微处理器或微控制器上运
行。uc/os和uclinux都是源码公开的操作系统,且其结构化设计便于把与处理
器相关的部分分离出来,所以被移植到新的处理器上是可能的。
以下对两种系统的移植分别予以说明。
(1)uc/os的移植
要移植uc/os,目标处理器必须满足以下要求;
·处理器的c编译器能产生可重入代码,且用c语言就可以打开和关闭中断;
·处理器支持中断,并能产生定时中断;
·处理器支持足够的ram(几k字节),作为多任务环境下的任务堆栈;
·处理器有将堆栈指针和其他cpu寄存器读出和存储到堆栈或内存中的指令。
在理解了处理器和c编译器的技术细节后,uc/os的移植只需要修改与处理器
相关的代码就可以了。具体有如下内容:
·os_cpu.h中需要设置一个常量来标识堆栈增长方向;
·os_cpu.h中需要声明几个用于开关中断和任务切换的宏;
·os_cpu.h中需要针对具体处理器的字长重新定义一系列数据类型;
·os_cpu_a.asm需要改写4个汇编语言的函数;
·os_cpu_c.c需要用c语言编写6个简单函数;
·修改主头文件include.h,将上面的三个文件和其他自己的头文件加入。
(2)uclinux的移植
由于uclinux其实是linux针对嵌入式系统的一种改良,其结构比较复杂,相对
uc/os,uclinux的移植也复杂得多。一般而言要移植uclinux,目标处理器除了
应满足上述uc/os应满足的条件外,还需要具有足够容量(几百k字节以上)外
部rom和ram。
uclinux的移植大致可以分为3个层次:
·结构层次的移植,如果待移植处理器的结构不同于任何已经支持的处理器结构,
则需要修改linux/arch目录下相关处理器结构的文件。虽然uclinux内核代码的
大部分是独立于处理器和其体系结构的,但是其最低级的代码也是特定于各个系
统的。这主要表现在它们的中断处理上下文、内存映射的维护、任务上下文和初
始化过程都是独特的。这些例行程序位于linux/arch/目录下。由于linux所支持
体系结构的种类繁多,所以对一个新型的体系,其低级例程可以模仿与其相似的
体系例程编写。
·平台层次的移植,如果待移植处理器是某种uclinux已支持体系的分支处理器,
则需要在相关体系结构目录下建立相应目录并编写相应代码。如mc68ez328就
是基于无mmu的m68k内核的。此时的移植需要创建
linux/arch/m68knommu/platform/ mc68ez328目录并在其下编写跟踪程序(实现
用户程序到内核函数的接口等功能)、中断控制调度程序和向量初始化程序等。
·板级移植,如果你所用处理器已被uclinux支持的话,就只需要板级移植了。板
级移植需要在linux/arch/?platform/中建立一个相应板的目录,再在其中建立相应
的启动代码crt0_rom.s或crt0_ram.s和链接描述文档rom.ld或ram.ld就可以了。
板级移植还包括驱动程序的编写和环境变量设置等内容。
通过对uc/os和uclinux的比较,可以看出这两种操作系统在应用方面各有优劣。
uc/os占用空间少,执行效率高,实时性能优良,且针对新处理器的移植相对简
单。uclinux则占用空间相对较大,实时性能一般,针对新处理器的移植相对复
杂。但是,uclinux具有对多种文件系统的支持能力、内嵌了tcp/ip协议,可
以借鉴linux丰富的资源,对一些复杂的应用,uclinux具有相当优势。例如cisco
公司的 2500/3000/4000 路由器就是基于uclinux操作系统开发的。
总之,操作系统的选择是由嵌入式系统的需求决定的。简单的说就是,小型控制
系统可充分利用uc/os小巧且实时性强的优势,如果开发pda和互联网连接终
端等较为复杂的系统则uclinux是不错的选择。
⑥ UC/OS与Linux操作系统的区别
uc/os比较简单一点,开始学的uc/os,感觉没意思了就开始学linux,感觉ucos只是在单片机上跑跑,像arm9的一般是跑linux。其实先学哪个都差不多,因为学习方法大不相同,差别太大了,ucos太简单,就一些信号量,邮箱什么的,懂了也就会了,linux有点难,涉及知识太多,光是涉及内核以外的编程就需要大把大把的经典书籍去看。兴趣很重要,都靠兴趣过来的。
⑦ uC/OS-II的解决方法
对于这样的设计方式,CPU必须能够:
◆ 有相应的CPU寄存器能够模仿SP的一些功能,能使用相应的指令来完成类似SP的一些操作;
◆ 作为SP使用的寄存器在编译过程中最好不被编译器默认使用。在IAR的编译器中,有一个选项可以避免在编译过程中使用到R4、R5。
这两点MSP430都可以做到。
下面对一个正在运行的优先级为6的任务中断后,会发生的几种情况进行分析。
1)在中断的处理过程中没有更高优先级的中断产生,即不会产生中断嵌套。
图3所示为中断发生后对于任务优先级为6的任务堆栈所进行的操作。中断发生后,PC和SR被系统压栈②,对于IAR C编译器来说,会按照复杂度不同的中断服务程序的要求,默认地进行一些寄存器的压栈操作③。因为我们要求的堆栈格式是如图2所示的,我们要把SP调整到SR后面④,然后进行R4~R15的压栈操作,形成我们所要求的堆栈格式⑤。
进行任务堆栈的压栈工作以后,就可以调整SP的指针到系统堆栈了,如图4所示。压栈后的SP指向最后一个压栈内容①。我们把SP的值赋值给优先级6任务的TCB->OSTCBStkPtr,以便进行任务调度的时候出栈使用②。接着,就把SP调整到系统堆栈处③。在中断处理过程中,可能会出现压栈的操作,那么这种情况下SP的指针会随之移动。由于是中断堆栈中,所以不会破坏任务堆栈的格式。
由于没有中断嵌套,在中断处理中没有别的中断发生,那么返回的步骤和上述的进栈操作正好相反。在中断处理完了以后,SP会自动回到图4中③的SP位置。接着,系统会查询到优先级最高的任务,然后把SP的指针移到优先级最高的任务的任务堆栈,进行R15~R4的出栈工作,最后用RETI中断返回指令返回到新的任务。因为我们把所有的任务堆栈都规定成相同的格式,所以它们之间不会产生问题。这里需要注意的是,因为系统在C编译器的中断处理中会对中断进入时默认压栈的寄存器出栈,所以在设计出栈的程序时,要先把这些内容压栈,这样才能正确出栈。
2)在中断的处理过程中,有别的中断产生,产生中断嵌套。
如图5所示,由于在处理中断的时候,SP已经被移到系统堆栈去了,只有当中断退出的时候才可能把SP移到别的任务的任务堆栈中。所以在中断的时候进行中断嵌套,那么对于中断的处理和第一次是一样的,所不同的是,这次保存在堆栈中的不是任务运行中的寄存器,而是中断处理中的寄存器,而且是保存在系统堆栈中而不是任务堆栈中。从这里就可以看出优化内存的效果。所有的中断嵌套中的寄存器压栈都压在系统堆栈中,这样对于任务堆栈内存大小的要求大大降低。
因为μC/OS-II在进入中断中,会把全局变量OSIntNesting++;在退出中断的时候,又会把OSIntNesting--。在退出中断进行任务切换之前,μC/OS-II会先判断OSIntNesting是否为0,是0才会进行任务调度。当第二中断运行结束以后,退出中断嵌套的时候,OSIntNesting不为0,也就不会进行任务调度。因此,仍旧在系统堆栈出栈,那么系统会继续前面没有完成的中断服务程序。
接着退出中断的顺序和非中断嵌套的顺序是一样的。在中断处理完以后,SP会自动回到图4中③的SP位置。接着,系统会查询到优先级最高的任务,然后把SP的指针移到优先级最高的任务的任务堆栈。进行R15~R4的出栈工作,最后用RETI中断返回指令返回到新的任务。
中断的情况基本上就是上述两种。对于有些文献中提到的在中断中会调度到更高优先级的任务的情况,笔者觉得是不应该发生的。因为从上面的分析可以看出,默认的(μC/OS-II的设计思路)中断处理会同时对全局变量OSIntNesting进行增减处理,以给出是否需要任务调度的条件。那么即使在中断服务程序中把更高优先级的任务就绪,也会等到中断退出以后再进行调度,除非是在中断中直接调用更高优先级的任务函数。但这种方法应该是和μC/OS-II的原则相违背的,沿用的是以前前后台设计的思路。
对于这样的设计方式,时钟节拍的处理方式必须和一般的中断处理方式是一样的。一般来说,MSP430使用WATCHDOG时钟中断作为时钟节拍的产生源。从本质上来说,时钟节拍本身也是中断处理过程,所以对于时钟节拍的处理应该和其它的中断处理过程相同。实际上,在时钟节拍的处理过程中也可能会存在中断嵌套的问题。
中断堆栈和任务堆栈分离设计的程序流程如图6所示。
⑧ 什么是UC/OS-2怎样学习它
uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的、可裁减的、抢占式、实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和很多商业操作系统性能相当的实时操作系统(RTOS)。为了提供最好的移植性能,uC/OS II最大程度上使用ANSI C语言进行开发,并且已经移植到近40多种处理器体系上,涵盖了从8位到64位各种CPU(包括DSP)。 uC/OS II可以简单的视为一个多任务调度器,在这个任务调度器之上完善并添加了和多任务操作系统相关的系统服务,如信号量、邮箱等。其主要特点有公开源代码,代码结构清晰、明了,注释详尽,组织有条理,可移植性好,可裁剪,可固化。内核属于抢占式,最多可以管理60个任务。从1992年开始,由于高度可靠性、鲁棒性和安全性,uC/OS II已经广泛使用在从照相机到航空电子产品的各种应用中。
uC/OS是嵌入式实时系统,主要是MCU(51, AVR, STM, ARM等)上运行,你可以在Keil环境下学习uC/OS,但是,由于Keil为交差编译器,编译的程序都是针对于具体MCU,并不能直接在Windows平台下运行,所以你要运行程序只能在特定硬件平台(比如开发板)上运行或仿真软件上运行了。
如果初学,推荐使用51单片机上学习uC/OS,因为51历史悠久,资料极其丰富,网上有大量uC/OS在51单片机上移植的代码,而且有现成的Proteus仿真设计。
⑨ 嵌入式系统uc/os-II移植中,OS_CPU.H中有关数据类型的定义时,问题如下
typedef unsigned char BOOLEAN;的意思是将BOOLEAN定义为无符号的char类型,其作用就是你如果用"BOOLEAN b_complete;"声明b_complete变量相当于用"usigned char b_complete"。
int类型数据根据编译器的不同具有不同的长度,例如一些长度为16位一些为32位。如果你用short int那么不同编译器会为变量分不同长度的空间(16位?32位?),从而不知道是否会溢出,当然不好移植了(都不知道变量的值会不会溢出)。而char的度在C编译器中长度都是8位(java中好像为16位),所以定义INT8S INT8U肯定用char了。
至于这句话:“uc/os-II系统的代码不适用C语言中的short int等数据类型,因为他们是编译器相关的,是不可移植的。相反,定义的整形数据结构等是可易移植的。”的意思是:在程序中不会出现什么int和short int等长度根据编译器变化而变化的数据类型,需要进行变量声明时会用INT8S INT16S INT8U INT16U等代替,然后根据编译环境不同只修改“typedef signed char INT8S; ”这些类型定义就行,用这样的整形数据结构移植方便,不用修改每个个地方,如果不这样,有变量声明的地方移植就要改,那么移植工作量将会是一个非常恐怖的事情,相信没有人愿意这样的事吧。