《(ppt)嵌入式系统RTEOSμCII的移植》由会员分享,可在线阅读,更多相关《(ppt)嵌入式系统RTEOSμCII的移植(103页珍藏版)》请在金锄头文库上搜索。
1、嵌入式系统嵌入式系统 RTEOS C/OS-II 的移植 04工程实训工程实训软件学院软件学院软件学院软件学院主要内容n移植规划移植规划nC/OS-II的移植的移植n嵌入式系统的初始化嵌入式系统的初始化 移植规划-概述 所谓“移植”,就是使一个实时内核能在其它的微处理器或微控制器上运行。 尽管大部分C/OS-II的代码是用C语言编写的,但是在编写与处理器硬件相关的代码时还是不得不使用汇编语言。 移植的主要工作就是编写这些与处理器硬件相关的代码。 操作系统的移植大体可以分为两个层次:n跨体系结构的移植n针对特定处理器的移植 移植规划 在移植前针对所使用的微处理器进行规划,主要有以下几个方面的考虑
2、:n 编译器的选择n 任务模式的选择n 支持的指令集 移植规划(续)编译器的选择n针对ARM处理器核的C语言编译器有很多,如SDT、 ADS、IAR、TASKING和GCC等n目前在国内最流行的是ADS、SDT和GCCnSDT和ADS均为ARM公司自己开发,ADS为SDT的升级版,以后ARM公司不再支持SDT,故不选择SDT。GCC虽然支持广泛,很多开发套件使用它作为编译器,但是与ADS比较其编译效率较低,这对充分发挥芯片性能不利n考虑使用ADS编译程序和调试ARMARM的工作模式的工作模式nARMARM处理器有处理器有7 7种操作模式种操作模式: :n用户模式用户模式(usr)(usr)n
3、- - 正常的程序执行模式正常的程序执行模式n快速中断模式快速中断模式(fiq)(fiq) - - 支持高速数据传输或通道处理支持高速数据传输或通道处理n中断模式中断模式(irq)(irq) - - 用于通用中断处理用于通用中断处理n管理员模式管理员模式(svc)(svc) - - 操作系统的保护模式操作系统的保护模式. .n中止模式中止模式(abt)(abt) - - 支持虚拟内存和支持虚拟内存和/ /或内存保护等异常或内存保护等异常n系统模式系统模式(sys)(sys) - - 支持操作系统的特殊用户模式支持操作系统的特殊用户模式( (运行操作系统任务)运行操作系统任务)n未定义模式未定义
4、模式(und)(und) - - 支持硬件协处理器的软件仿真支持硬件协处理器的软件仿真 n除了用户模式外,其他模式均可视为特权模式除了用户模式外,其他模式均可视为特权模式 移植规划(续)n任务模式的取舍 ARM7处理器核具有上述七种模式,其中除用户模式外其它均为特权模式。其中管理、中止、未定义、中断和快中断模式与相应异常相联系,任务使用这些模式不太适合。 系统模式除了是特权模式外,其它与用户模式一样,因而可选为任务使用的模式只有用户模式和系统模式。 为了尽量减少任务代码错误对整个程序的影响,缺省的任务模式定为用户模式,可选为系统模式,同时提供接口使任务可以在这两种模式间切换。移植规划(续)n支
5、持的指令集带T变量的ARM7处理器核具有两个指令集:n标准32位ARM指令集n16位Thumb指令集 两种指令集有不同的应用范围。n为了最大限度地支持芯片的特性,任务应当可以使用任意一个指令集并可以自由切换,而且不同的任务应当可以使用不同的指令集移植C/OS-IIn概述 要移植一个操作系统到一个特定的CPU体系结构并不是一件很容易的事情,它对移植者有以下要求:1 对目标体系结构要有很深了解;2 对OS原理要有较深入的了解;3 对所使用的编译器要有较深入的了解;4 对需要移植的操作系统要有相当的了解;5 对具体使用的芯片也要一定的了解 要移植一个操作系统到一个特定的CPU体系结构上并不是一件很容
6、易的事情,它对移植者有以下要求:1 对目标体系结构要有很深了解;2 对OS原理要有较深入的了解;3 对所使用的编译器要有较深入的了解;4 对需要移植的操作系统要有相当的了解;5 对具体使用的芯片也要一定的了解。 概述主要内容主要内容n移植规划移植规划nC/OS-II的移植的移植n嵌入式系统的初始化嵌入式系统的初始化 C/OSC/OS-II-II的文件结构的文件结构 C/OS-II移植应用程序(用户代码)C/OS-II(与处理器无关代码)OS_CORE.cOS_FLAG.c. C/OS-II配置(与应用相关)OS_CFG.HINCLUDES.H C/OS-II移植(与处理器相关代码)CPU定时器
7、 硬件软件C/OS-II硬件软件体系结构用于产生系统时钟移植时需要编写的代码移植移植 C/OS-II满足的条件满足的条件 n处理器的C编译器能产生可重入代码 n在程序中可以打开或者关闭中断 n处理器支持中断,并且能产生定时中断(通常在10100Hz之间) n处理器支持能够容纳一定量数据的硬件堆栈(通常是几千字节) n处理器有将堆栈指针和其他CPU寄存器的内容存储和读出到堆栈(或者内存)的指令 什么是可重入代码什么是可重入代码 n可重入的代码指的是一段可以被多个任务同时调用,而不必担心会破坏数据的代码(比如:一个函数)n即:可重入型函数在任何时候都可以被中断执行,过一段时间以后又可以继续运行,而
8、不会因为在函数中断的时候被其他的任务重新调用,而影响函数中的数据 可重入代码举例可重入代码举例程序1:可重入型函数void swap(int *x, int *y)int temp;temp=*x;*x=*y;*y=temp;非可重入代码举例非可重入代码举例程序2:非可重入型函数int temp;void swap(int *x, int *y)temp=*x;*x=*y;*y=temp;不可重入函数被中断破坏不可重入函数被中断破坏如何使函数具有可重入性如何使函数具有可重入性 使Swap()函数具有可重入性的条件:n把Temp定义为局部变量n调用Swap()函数之前关中断,调用 后再开中断n用
9、信号量禁止该函数在使用过程中 被再次调用 概述 根据C/OS-II的要求,移植C/OS-II到一个新的体系结构上需要提供2个或3个文件: OS_CPU.H(C语言头文件) OS_CPU_C.C(C程序源文件) OS_CPU_A.ASM(汇编程序源文件) 其中OS_CPU_A.ASM在某些情况下不需要,但极其罕见。不需要OS_CPU_A.ASM的必须满足以下苛刻条件: 1.可以直接使用C语言开关中断; 2.可以直接使用C语言编写中断服务程序; 3.可以直接使用C语言操作堆栈指针; 4.可以直接使用C语言保存CPU的所有寄存器。 移植需要编写的文件 概述移植内容类型所属文件描述BOOLEAN、IN
10、T8U、INT8S、数据类型OS_CPU.H与编译器无关的数据类型OS_STK数据类型OS_CPU.H堆栈的数据类型OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()宏OS_CPU.H开关中断的代码OS_STK_GROWTH常量OS_CPU.H定义堆栈的增长方向OS_TASK_SW函数OS_CPU.H任务切换时执行的代码OSTaskStkInit()函数OS_CPU_C.C任务堆栈初始化函数OSInitHookBegin()、OSInitHookEnd()、函数OS_CPU_C.CC/OS-II在执行某些操作时调用的用户函数,一般为空OSStartHighRdy()函
11、数*OS_CPU_A.ASM进入多任务环境时运行优先级最高的任务, OSIntCtxSw()函数*OS_CPU_A.ASM中断退出时的任务切换函数OSTickISR()中断服务程序*OS_CPU_A.ASM时钟节拍中断服务程序 实际上,还有一个文件很重要,它就是IRQ.INC,它定义了一个汇编宏,它是C/OS-II for ARM7通用的中断服务程序的汇编与C函数接口代码接口代码。时钟节拍中断服务程序也没有移植,因为其与芯片和应用都强烈相关,需要用户自己编写,不过可以通过IRQ.INC简化用户代码的编写。 移植代码包括的主要内容关于头文件includes.h和config.hn C/OS-II
12、要求所有.C文件的都要包含头文件includes.h,这样使得用户项目中的每个.C文件不用分别去考虑它实际上需要哪些头文件。n 使用INCLUDES.H的缺点是它可能会包含一些实际不相关的头文件,这意味着每个文件的编译时间可能会增加,但却增强了代码的可移植性。 在移植中另外增加了一个头文件config.h,要求所有用户程序必须包含config.h,在config.h中包含includes.h和特定的头文件和配置项。而C/OS-II的系统文件依然只是包含includes.h,即C/OS-II的系统文件完全不必改动。所有的配置改变包括头文件的增减均在config.h中进行,而includes.h定
13、下来后不必改动(C/OS-II的系统文件需要包含的东西是固定的)。这样,C/OS-II的系统文件需要编译的次数大大减少,编译时间随之减少。 congfig.hUC/OS内核文件Includes.h用户程序设置与处理器和编译器相关的代码设置与处理器和编译器相关的代码nOS_CPU.H中定义了与编译器相关的数据类型。比如:INT8U、INT8S等。n与 ARM处理器相关的代码,使用OS_ENTER_CRITICAL() 和OS_EXIT_CRITICAL() 宏开启关闭中断n设置堆栈的增长方向 :堆栈由高地址向低地址增长 编写OS_CPU.H C/OS-II使用结构常量OS_STK_GROWTH中
14、指定堆栈的生长方式:置OS_STK_GROWTH为0表示堆栈从下往上长。 置OS_STK_GROWTH为1表示堆栈从上(高地址)(高地址)往下(低地址)(低地址)长。 虽然ARM处理器核对于两种方式均支持,但ADS的C语言编译器仅支持一种方式,即从上往下长,并且必须是满递减堆栈,所以OS_STK_GROWTH的值为1。#define OS_STK_GROWTH 1 堆栈生长方式 编写OS_CPU.H C/OS-II不使用C语言中的short、int、long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性与处理器类型有关,隐含着不可移植性。代之以移植性强的整数数据类型,这样,既直观
15、又可移植,不过这就成了必须移植的代码。根据ADS编译器的特性,这些代码如下程序清单所示(与编译有关)。typedefunsigned char BOOLEAN; typedefunsigned char INT8U;typedefsigned char INT8S;typedefunsigned short INT16U;typedefsigned short INT16S;typedefunsigned int INT32U;typedefsigned int INT32S;typedeffloat FP32;typedefdouble FP64;typedefINT32U OS_STK;不
16、依赖于编译的数据类型设置设置includes.htypedef unsigned char BOOLEAN;typedef unsigned char INT8U; typedef signed char INT8S; typedef unsigned int INT16U; typedef signed int INT16S; typedef unsigned long INT32U; typedef signed long INT32S; typedef float FP32; typedef double FP64; typedef unsigned long OS_STK; typed
17、ef unsigned long OS_CPU_SR; extern int INTS_OFF(void); extern void INTS_ON(void);#define OS_ENTER_CRITICAL() cpu_sr = INTS_OFF(); #define OS_EXIT_CRITICAL() if(cpu_sr = 0) INTS_ON(); #define OS_STK_GROWTH 1 /*从高向低*/程序状态寄存器程序状态寄存器(CPSR)n 条件位条件位:nN = 1-结果为负,0-结果为正或0nZ = 1-结果为0,0-结果不为0nC =1-进位,0-借位nV =
18、1-结果溢出,0结果没溢出nQ Q 位位:n仅ARM 5TE/J架构支持n指示增强型DSP指令是否溢出nJ J 位位n仅ARM 5TE/J架构支持nJ = 1: 处理器处于Jazelle状态n中断禁止位中断禁止位:nI = 1: 禁止 IRQ.nF = 1: 禁止 FIQ.nT BitT Bitn仅ARM xT架构支持nT = 0: 处理器处于 ARM 状态nT = 1: 处理器处于 Thumb 状态nModeMode位位( (处理器模式位处理器模式位):):n0b10000Usern0b10001FIQn0b10010IRQn0b10011Supervisorn0b10111Abortn0b
19、11011Undefinedn0b11111System2731N Z C V Q2867I F T mode1623 815 54024fsxc U n d e f i n e dJ 编写OS_CPU.H C/OS-II运行时,处理器可能处于的模式如下图所示:使用软中断SWI作底层接口Thumb指令集ARM指令集用户模式系统模式用户任务使用的处理器模式ARM7内核具有的指令集ARM指令用户模式ARM指令系统模式Thumb指令系统模式Thumb指令用户模式 编写OS_CPU.H 为了使底层接口函数与处理器状态无关,同时在任务调用相应的函数不需要知道函数位置,在移植中使用软中断指令SWI作为底层
20、接口,使用不同的功能号区分不同的函数。软中断功能号分配如下表所示,未列出的为保留功能。 使用软中断SWI作底层接口功能号接口函数简介0x00void OS_TASK_SW(void)任务级任务切换函数0x01_OSStartHighRdy(void)运行优先级最高的任务,由OSStartHighRdy产生0x02void OS_ENTER_CRITICAL(void)关中断0x03Void OS_EXIT_CRITICAL(void)开中断0x80Void ChangeToSYSMode(void)任务切换到系统模式0x81Void ChangeToUSRMode(void)任务切换到用户模式
21、0x82Void TaskIsARM(INT8U prio)任务代码是ARM代码0x83Void TaskIsTHUMB(INT8U prio)任务代码是THUMB代码 编写OS_CPU.H 用软中断作为操作系统的底层接口就需要在C语言中使用SWI(SoftWare Interrupt)指令。在ADS中,有一个关键字_swi,用它声明一个不存在的函数,则调用这个函数就在调用这个函数的地方插入一条SWI指令,并且可以指定功能号。同时,这个函数也可以有参数和返回值,其传递规则与一般函数相同。 使用软中断SWI作底层接口/* 任务级任务切换函数 */_swi(0x00) void OS_TASK_S
22、W(void); /* 运行优先级最高的任务 */_swi(0x01) void _OSStartHighRdy(void); /* 关中断 */_swi(0x02) void OS_ENTER_CRITICAL(void); /* 开中断 */_swi(0x03) void OS_EXIT_CRITICAL(void); /* 任务切换到系统模式 */_swi(0x80) void ChangeToSYSMode(void); /* 任务切换到用户模式 */_swi(0x81) void ChangeToUSRMode(void); /* 任务代码是ARM代码 */_swi(0x82) vo
23、id TaskIsARM(INT8U prio);/* 任务代码是THUMB代码 */_swi(0x83) void TaskIsTHUMB(INT8U prio);程序中调用软中断时使用的函数名软件中断号该调用不返回参数编写OS_CPU_C.CnC/OS-IIC/OS-II的移植要求用户编写的移植要求用户编写1010个个C C函数:函数:nOSTaskStkInitOSTaskStkInit():(): OSTaskCreat OSTaskCreat()和()和OSTaskCreatExtOSTaskCreatExt()通过调用()通过调用 本函数,初始化任务的栈结构本函数,初始化任务的栈结
24、构nOSTaskCreateHookOSTaskCreateHook():每当添加任务时由():每当添加任务时由OS_TCBInit( )OS_TCBInit( )函数调用函数调用nOSTaskDelHookOSTaskDelHook():(): 任务被删除后由任务被删除后由OSTaskDelOSTaskDel()调用()调用nOSTaskSwHookOSTaskSwHook():(): 任务切换时两种情况均会调用该函数任务切换时两种情况均会调用该函数nOSTaskIdleHookOSTaskIdleHook():():OSTaskIdleOSTaskIdle()函数可调用该函数实现()函数可
25、调用该函数实现CPUCPU低功耗模式低功耗模式nOSTimeTickHookOSTimeTickHook():本函数在每个时钟节拍都会被():本函数在每个时钟节拍都会被OSTimeTickOSTimeTick()调用()调用nOSInitHookBeginOSInitHookBegin():进入():进入OSInitOSInit()函数后本函数会立即被调用()函数后本函数会立即被调用nOSInitHookEndOSInitHookEnd():(): OSInit OSInit()函数返回之前被调用()函数返回之前被调用nOSTCBInitHookOSTCBInitHook():():OS_TC
26、BInit( )OS_TCBInit( )在调用在调用OSTaskCreateHookOSTaskCreateHook()之前将先()之前将先 调用本函数调用本函数n唯一必要的函数是唯一必要的函数是OStaskStkInitOStaskStkInit(),其他(),其他9 9个函数必须声明,但不一定个函数必须声明,但不一定要包含任何代码要包含任何代码编写OS_CPU_C.C 该函数用于初始化任务堆栈,使任务的堆栈看起来就像刚发生中断一样。即任务被执行时,就像从中断返回一样。 在编写此函数之前,必须先确定任务的堆栈结构。而任务的堆栈结构是与CPU的体系结构、编译器有密切的关联。本移植的堆栈结构如
27、下图所示。 OSTaskStkInit( )任务入栈的其它数据LRR12R11R10R9R8. 栈底 任务环境开始 SPPCR2R1R0OSEnterSum空闲空间编写OS_CPU_C.COSTaskStkInit( )OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) OS_STK *stk; opt = opt; stk = ptos; *stk = (OS_STK) task; *-stk = (OS_STK) task; *-stk = 0; *-stk = 0; *
28、-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = (unsigned int) pdata; *-stk = (USER_USING_MODE|0x00); *-stk = 0; return (stk); 入栈的数据任务入栈的其它数据LRR12R11R10R9R8. 栈底 任务环境开始 SPPCR2R1R0OSEnterSum空闲空间编写OS_CPU_C.COSTaskStkInit( )OS_STK *OST
29、askStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) OS_STK *stk; opt = opt; stk = ptos; *stk = (OS_STK) task; *-stk = (OS_STK) task; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = (uns
30、igned int) pdata; *-stk = (USER_USING_MODE|0x00); *-stk = 0; return (stk); 该数据比较特别,它用于保存该任务关中断的次数,它在调用OS_ENTER_CRITICAL( )时加1,在调用OS_EXIT_CRITICAL( )时减1。 这样每个任务都可以独立控制本任务的中断允许状态,而不会影响其它任务的中断允许状态。因此关中断和开中断就可以嵌套。 编写OS_CPU_C.C软件中断异常服务程序 操作系统与硬件相关的底层函数使用软件中断作为接口,如下表所示。n 移植代码中一个重要的工作就是为这些软件中断编写服务程序功能号接口函数
31、简介0x00void OS_TASK_SW(void)任务级任务切换函数0x01_OSStartHighRdy(void)运行优先级最高的任务,由OSStartHighRdy产生0x02void OS_ENTER_CRITICAL(void)关中断0x03Void OS_EXIT_CRITICAL(void)开中断0x80Void ChangeToSYSMode(void)任务切换到系统模式0x81Void ChangeToUSRMode(void)任务切换到用户模式0x82Void TaskIsARM(INT8U prio)任务代码是ARM代码0x83Void TaskIsTHUMB(INT
32、8U prio)任务代码是THUMB代码编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码功能号接口函数简介0x00void OS_TASK_SW(void)任务级任务切换函数0x01_OSStartHighRdy(void)运行优先级最高的任务,由OSStartHighRdy产生0x02void OS_ENTER_CRITICAL(void)关中断0x03Voi
33、d OS_EXIT_CRITICAL(void)开中断0x80Void ChangeToSYSMode(void)任务切换到系统模式0x81Void ChangeToUSRMode(void)任务切换到用户模式0x82Void TaskIsARM(INT8U prio)任务代码是ARM代码0x83Void TaskIsTHUMB(INT8U prio)任务代码是THUMB代码void SWI_Exception(int SWI_Num, int *Regs) OS_TCB *ptcb; switch(SWI_Num) case 0x02: / 关中断 . case 0x03: / 开中断 .
34、case 0x80: / 任务切换到系统模式 . case 0x81: / 任务切换到用户模式 . case 0x82: / 任务代码是ARM代码 . case 0x83: / 任务代码是Thumb代码 . default: 这两个软件中断使用汇编代码完成编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码 C/OS-II的启动多任务环境的函数叫做OSStart()
35、,用户在调用OSStart()之前,必须已经建立了一个或更多任务。OSStart()最终调用函数OSStartHighRdy()运行多任务启动前优先级最高的任务。 void OSStartHighRdy(void) _OSStartHighRdy(); 该函数在Os_cpu_a.s文件中实现。编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码 关中断和开中断是为了
36、保护临界段代码。这些代码与处理器有关,是需要移植的代码。在ARM处理器核中关中断和开中断时通过改变程序状态寄存器CPSR中的相应控制位实现。由于使用了软件中断,程序状态寄存器CPSR保存到程序状态保存寄存器SPSR中,软件中断退出时会将SPSR恢复到CPSR中,所以程序只要改变程序状态保存寄存器SPSR中的相应的控制位就可以了。 编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码
37、是THUMB代码void SWI_Exception(int SWI_Num, int *Regs) . case 0x02: / 关中断 _asm MRS R0,SPSR ORR R0,R0,#NoInt MSR SPSR_c,R0 OsEnterSum+; break; case 0x03: / 开中断 if (-OsEnterSum = 0) _asm MRS R0,SPSR BIC R0,R0,#NoInt MSR SPSR_c,R0 break; .每关闭一次中断,中断关闭计数器加1每调用一次开中断函数,该计数器减1,为0时允许打开中断关闭中断打开中断编写OS_CPU_C.C软件中断
38、异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码 它们可以在任何情况下使用。它们改变程序状态保留寄存器程序状态保留寄存器SPSRSPSR的相应位段,而程序状态保留寄存器会在软件中断退出时复制到程序状态寄程序状态寄存器存器CPSRCPSR,任务的处理器模式就改变了。 编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHi
39、ghRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码void SWI_Exception(int SWI_Num, int *Regs) . case 0x80: / 任务切换到系统模式 _asm MRS R0,SPSR BIC R0,R0,#0x1f ORR R0,R0,#SYS32Mode MSR SPSR_c,R0 break; case 0x81: / 任务切换到用户模式 _asm MRS R0,SPSR BIC R0,R0,#0x1f ORR R0,R0,#USR32Mode MSR
40、 SPSR_c,R0 break; .使用内嵌汇编将处理器模式切换到用户模式使用内嵌汇编将处理器模式切换到系统模式编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码 任务可以使用ARM的两种指令集的任意一种运行,但是任务建立时默认的只是一种指令集。如果任务使用的第一条指令与默认的指令集不同,则程序运行错误。所以增加两个函数TaskIsARM()和TaskIsTHU
41、MB()用于改变任务建立时用于改变任务建立时默认的指令集。默认的指令集。 它们都有唯一的参数:需要改变的任务的优先级,值得注意的是,这两个函数必须在相应的任务建立后但还没有运行时调用。 编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码 . case 0x82: / 任务代码是ARM代码 if (Regs0 OSTCBStkPtr1 &= (1 5); break
42、; case 0x83: / 任务代码是Thumb代码 if (Regs0 OSTCBStkPtr1 |= (1 5); break; .被设置的任务号一定不能大于最低优先级任务获取指定任务的任务控制块的地址修改任务堆栈中CPSR的值,在任务重新运行时,切换到ARM指令方式修改任务堆栈中CPSR的值,在任务重新运行时,切换到Thumb指令方式CPSR:程序状态寄存器程序状态寄存器编写OS_CPU_C.C软件中断异常服务程序功能号简介0x00任务级任务切换函数0x01运行优先级最高的任务,由OSStartHighRdy产生0x02关中断0x03开中断0x80任务切换到系统模式0x81任务切换到用
43、户模式0x82任务代码是ARM代码0x83任务代码是THUMB代码注意: 这两个函数必须在相应的任务建立后但还没有运行时调用。 如果在低优先级的任务中创建高优先级的任务就十分危险了。此时,解决的方法有三种:(1)高优先级任务使用默认的指令集;(2)改变函数OSTaskCreateHook()使任务默认不是处于就绪状态,建立任务后调用函数OSTaskResume()来使任务进入就绪状态;(3)建立任务时禁止任务切换,调用函数 TaskIsARM()或TaskIsTHUMB()后再允许任务切换。编写OS_CPU_C.C 在Os_cpu_c.c文件中还有许多Hook()函数,它们在某个特定的系统动作
44、时被调用,允许执行函数中的用户代码。这些函数默认是空函数,用户根据实际情况添加相关代码。它们分别如下表所示。Hook( )函数函数名被执行条件OSInitHookBegin( )在开始执行OSInit( )函数时被执行OSInitHookEnd( )在OSInit()函数结束时被执行OSTaskCreateHook( )在任务建立时被调用OSTaskDelHook( )在任务删除时被调用OSTaskSwHook( )在进行任务切换时被调用OSTaskStatHook( )被统计任务调用,每秒执行一次OSTCBInitHook( )在建立所有的TCB后,由OSTCBInit函数调用OSTimeT
45、ickHook( )每个时钟节拍产生后被调用OSTaskIdleHook( )由空闲任务调用 移植C/OS-IIn编写OS_CPU_A.ASM在OS_CPU_A.ASM文件中有:n软件中断的汇编接口程序n任务切换程序nOS启动时运行就绪最高优先级任务的程序OS_CPU_A.ASMnC/OS-II的移植要求用户编写4个汇编语言函数:nOSStartHighRdy()nOSCtxSw()nOSIntCtxSw()nOSTickISR()n如果编译器支持插入行汇编代码,就可以将所有与处理器相关的代码放到OS_CPU_C.C文件中,而不必再有单独的汇编语言文件 编写OS_CPU_A.ASM 在调用软中
46、断之后,处理器切换到ARM指令和管理模式下工作。在执行软件中断服务函数之前,要提取中断号和其它入口参数,这些通过软件中断接口程序完成。软件中断汇编接口SoftwareInterrupt LDR SP, StackSvc STMFD SP!, R0-R3, R12, LR MOV R1, SP MRS R3, SPSR TST R3, #T_bit LDRNEH R0, LR,#-2 BICNE R0, R0, #0xff00 LDREQ R0, LR,#-4 BICEQ R0, R0, #0xFF000000 CMP R0, #1 LDRLO PC, =OSIntCtxSw LDREQ PC,
47、 =_OSStartHighRdy BL SWI_Exception LDMFD SP!, R0-R3, R12, PC 保护被中断的现场将要用到的寄存器压栈判断中断前的指令集类型从产生软件中断的指令中提取中断号ARMThumb根据不同的中断号执行不同的程序返回被中断的任务中断号执行程序0进行任务切换1启动多任务环境,运行就绪的最高优先级任务其它软件中断服务函数 编写OS_CPU_A.ASM C/OS-II是抢占式实时操作系统,得到运行的始终是就绪条件下最高优先级的任务。当处于运行状态的任务因为某种原因进入就绪态,或者有其它更高优先级的任务进入就绪态,操作系统内核就要运行别的就绪任务,这时需要
48、进行任务切换。 任务切换代码编写OS_CPU_A.ASM 任务切换代码任务切换可能发生的情况有两种任务切换可能发生的情况有两种: 1.当前运行的任务主动交出CPU控制权,通常发生在等待某个事件或是调用系统延时。调用函数OS_TASK_SW( ) 2.发生中断,使更高优先级的任务进入就绪状态,内核剥夺当前任务的运行资格。即发生在中断退出时。调用函数OSIntCtxSw( )SPSR:程序状态保留寄存器程序状态保留寄存器CPSR:当前当前程序状态寄存器程序状态寄存器 编写OS_CPU_A.ASM 虽然OS_TASK_SW( )和OSIntCtxSw( )的执行条件不同,但是它们的功能相同,只要稍作
49、处理就可以它们共用一段任务切换代码。这些处理就是保证在执行任务切换前两者的任务现场是一致的。共同执行的任务切换代码是“OSIntCtxSw” 其中OS_TASK_SW( )是通过软件中断软件中断0完成的,通过前面的分析,可以知道执行任务切换时的现场环境如下所示,同时R3中保存着SPSR,它是任务中断前CPSR的备份。任务切换代码任务入栈的其它数据LRR12R3R2R1R0空闲空间 栈底 任务环境开始 SP 编写OS_CPU_A.ASMOSIntCtxSw保存当前任务的寄存器组及其它修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioHighRdy和OSTCBCur恢复
50、新任务的寄存器组及其它运行新任务流程图 编写OS_CPU_A.ASMOSIntCtxSw保存当前任务的寄存器组及其它修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioHighRdy和OSTCBCur恢复新任务的寄存器组及其它运行新任务流程图OSIntCtxSw ;下面为保存任务环境 LDR R2, SP, #20 ;获取PC LDR R12, SP, #16 ;获取R12 MRS R0, CPSR ;保存LR,PC及R4-R12 MSR CPSR_c, #(NoInt | SYS32Mode) MOV R1, LR STMFD SP!, R1-R2 STMFD SP
51、!, R4-R12 ;获取R0-R3,并出栈R12和PC寄存器 MSR CPSR_c, R0 LDMFD SP!, R4-R7 ADD SP, SP, #8 ;保存R0-R3 MSR CPSR_c, #(NoInt | SYS32Mode) STMFD SP!, R4-R7 ;获取OsEnterSum,并保存CPSR,OsEnterSum LDR R1, =OsEnterSum LDR R2, R1 STMFD SP!, R2, R3 .PCLRR12R11R10R9R7R5R4R3R2R1R0R6R8CPSROSEnterSum切换至系统模式获取任务运行时的各寄存器并将它们压栈恢复之前的模式
52、读出压栈的数据任务环境保存结束后的栈结构 编写OS_CPU_A.ASMOSIntCtxSw修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioHighRdy和OSTCBCur保存当前任务的寄存器组及其它恢复新任务的寄存器组及其它运行新任务OSIntCtxSw . ;保存当前任务堆栈指针到当前任务的TCB LDR R1, =OSTCBCur LDR R1, R1 STR SP, R1 BL STaskSwHook ;调用钩子函数 ;OSPrioCur = OSPrioHighRdy LDR R4, =OSPrioCur LDR R5, =OSPrioHighRdy LD
53、RB R6, R5 STRB R6, R4 ;OSTCBCur R0BIC R0, R0, #MODEMASK ; 安全起见,屏蔽模式位以外的其它位ORR R1, R0, #IRQMODE ; 把设置模式位设置成需要的模式(IRQ)MSR CPSR_cxsf, R1 ; 转到IRQ 模式LDR SP, =UndefStack ; 设置SP_irqORR R1,R0,#FIQMODEMSR CPSR_cxsf, R1 ; FIQModeLDR SP, =FIQStackORR R1, R0, #SVCMODEMSR CPSR_cxsf, R1 ; SVCModeLDR SP, =SVCStack
54、六、初始化应用程序执行环境六、初始化应用程序执行环境l映像一开始总是存储在映像一开始总是存储在ROM/Flash ROM/Flash 里面的,其里面的,其RO RO 部分既可部分既可以在以在ROM/FlashROM/Flash里面执行,也可以转移到速度更快的里面执行,也可以转移到速度更快的RAM RAM 中中去;而去;而RW RW 和和ZI ZI 这两部分必须是需要转移到可写的这两部分必须是需要转移到可写的RAM RAM 里里去的。所谓应用程序执行环境的初始化,就是完成必要的去的。所谓应用程序执行环境的初始化,就是完成必要的从从ROM ROM 到到RAM RAM 的数据传输和内容清零。的数据传
55、输和内容清零。六、初始化六、初始化C C环境环境n在目标文件中,代码、数据放在不同的段中。源文件编译链接生成含.data、.text段的目标文件,且链接器生成的.data段是以系统RAM为参考地址n故在系统启动时需要拷贝ROM或FLASH中的.data段到RAM,以完成对RAM的初始化。在初始化期间应将系统需要读写的数据和变量从ROM拷贝到RAM里运行链接器产生的符号表链接器产生的符号表n符号由链接器自动产生,只读段(read-only RO)就是代码段,读写段(read-write RW)是已经初始化的全局变量,而零初始化段(zero-initialized section ZI)中存放未初
56、始化的全局变量;初始化初始化C C环境(环境(2 2)nC环境初始化,就是利用上述符号初始化RW和ZI段以使后面使用的全局变量的C程序正常运行;n这里有两个循环,第一个循环把预初始化的数据段RW(位于代码段的后面)复制到RAM中,另一个循环把未初始化的数据段ZI初始化为0,也就是实现把从ROM中的.data段拷贝到RAM,对ZI段内的数据初始化为0,以完成对C环境的实始化;初始化初始化C C环境(环境(3 3)改变处理器模式改变处理器模式l除用户模式以外,其他除用户模式以外,其他6 6 种模式都是特权模式。因为在种模式都是特权模式。因为在初始化过程中许多操作需要在特权模式下才能进行(比初始化过
57、程中许多操作需要在特权模式下才能进行(比如如CPSR CPSR 的修改),所以要特别注意不能过早地进入用的修改),所以要特别注意不能过早地进入用户模式。一般地,在初始化过程中会经历以下一些模式户模式。一般地,在初始化过程中会经历以下一些模式变化:变化:七、七、调用调用C C程序程序n对main函数的调用进入uc/OS的入口,通过这个入口就进入uC/OS的主函数,启动对uC/OS的初始化n例 IMPORT Main b Main ;C EntryuC/OSuC/OS系统的初始化系统的初始化n完成了前面的硬件初始化和运行环境的相关设置后,进入Main(), Main()是uC/OS的入口函数,启动
58、对uC/OS的初始化ARMARM的硬件抽象层的硬件抽象层uHALuC/OSuHALuC/OSnARM公司为操作系统的开发提供了一个硬件抽象层HAL,称为uHAL;n从结构上看,uHAL是一组库程序,需要说明的是,uHAL并不是专门为uC/OS准备的,甚至也不是专为操作系统内核准备的;nuHAL只是个针对ARM核的函数库;nuC/OS是建立在uHAL的基础之上的;uC/OSuC/OS系统的初始化(系统的初始化(2 2)ARMTargetInit()ARMTargetInit()函数结构函数结构ARMTargetInit()ARMTargetInit()调调uHALuHAL打印接口打印系统信息打印
59、接口打印系统信息调用调用uHALuHAL函数禁止所有中断函数禁止所有中断调用调用uHALuHAL函数对中断初始化函数对中断初始化uHALuHAL函数对函数对ARMARM计数器初始化计数器初始化结束结束uHALuHAL的功能的功能nuHAL的作用之一是在操作系统本身进入正常运行之前,为系统提供基本的输入输出手段,例如uHALr_printf()等;nuHAL还要为操作系统的运行准备一个基本的运行环境,具体包括下列各种初始化:n通过uHAL_ResetMMU(),将MMU设置在一个确定的初始状态;n通过ARMDisable()关闭中断;n通过uHAL_InitInterrupts()设置中断向量处
60、理程序;n通过uHAL_InitTimer()对系统使用的计数器进行初始化ARMTargetStart()ARMTargetStart()的分析的分析n创建了任务之后,ARMTargetStart()调用uHALr_InstallSystemTimer()创建一个系统时钟,为时钟中断做好准备;%90Z2-01r$t3ojNHIM)RyzQu+vP+!P$KYf04*K!MfvhHKlMPTJ2-0z3lgLoW7U3e4gP9-lhMUKAQT2(E$p6V8kyu2xeTwTe8wKD+YaMpk3psxDUz(GY%nU6&frLYay!&mMGlyC!jkpPDb0of)4HCf#xqV
61、zvrD*2-6Yl)#LjDQdKWUBZiGO%9k)1dK#K*k3X#Qk67Dm11ej29l%+p2VQ3GT)ZU)db&yU4xpzXjIq*dfdc6qxGVh&mA5X)zjiIJI6$QHHWRCbuKdzWYKj#OzNTXlt5U8y1n9KCX#VralgWm$wDVW2U+uwgdHIqRGt#tYLVDDwpS3v)%VkkI-uBpAKqV$*TPsw&T71680iUl(vYJs070mi0X5nz2LR(FG1Ayz%8nIWCOIF2XPPzugfX&xGh9qapaCTEIW61AbK3aq%z-H%iUOQmSq39!mOh$zztC&G!XwLuW
62、v2QK3W#g$y+%B$g*L3#JF-Igbc$&t8!g*3gAIHu-3uYFL5Mb)5Hf16Xg4iXS&Xbo-0aMHXptuvKd*ThPBptUMH8KxMs2ttKoTajn97A+NFzDPnLnXtOFr!5QqNJ-WAXxzC(vz2L*)$)v#ZfWRYqQNp5XCe0dV$AkfSWKH09u$XsiOX$VLpjI-7z&1W0QgfNr#*0YEk!ScRD6B9nOKveiOX-I9Zl($QJEbMU5$Azrd7(-rOXjV6v2$C!5(f!er7vNoSR!G%7yAr(Weh9K#XEtWo-VYU2ugq86n5ZZfu72llXG
63、nQN9L!l!miN%dkBOY&3I+dd38L05yXImH4Y#YyTHYah%*Lrl-IOE-eh&24T1ljlpDV!7cpWZTThbbHp2qW+5VrikZoe3jQRBk8oywxtlqpYgtMv3pS#5Nz%uEr0ejVW4fmYT*S)e-p!ejXJE#rp7tp1UMUEKq1-Co+2%4k3TXyNyNSzPe%4m*7IrNI1dirih2&Lon+BB(I*1Dd!Z#oWhpVDSEK-CamxYBYVPJfIVboS9-c%lB)N(gKTAph2)Rbj$p#s9M!ea&xKQ$b)T1+fRK9aC7M(Oopczx(pJO&Pfi$Kt
64、3F%$B*4lKOJBT$lbw6Y9KkGmB&yoQ(vu39FK6#2zY3j-9MX4!XubBR9BEzxr(3tR79e7*9k)rUh4ABkx3BiImecb82H85f-e3NQyVb71#Stz#QNkuthv&3JKY8c)C28J1)JI9l77k9YB5JNeg9KmFVJ8b28hJ9TDjXjiURcMWXn6ggf+JqT&prcg+QtDNxYSbgkEdS1wjFrH0j#4!&6Nb9FIMJCD-ld$i9!dI2KLFX9WT6uvTl(vrQ4k52w7nxLfvKvS7aEh6KqjOib)(FBuQnl+$4MPXc+X!Z4EnSa5O3z&
65、c)fB&+jnpBFAdvZP-Kquqx9373t4LhT%C9KK-BWGZk!dHlJPW*m*8(2*gYB3B-HsXRv&62)tpe9Zk0%&1YJjJk*7Vr-&QLZp5H7IfUCCoBB8GG&LQqAaRIPnVp5BjKi7BmrjOe$fx6I%It!9oqrYO4pWbZJv#uzBS7kkmTg7bLnN17Mwc50np$8S&*lkSElIDuOy-TuE$+H+5SshqgdK#7i2Pn%&X1Mkouq)H9D#zkI2CoMLQ6v%khmkMr+p2U7kmN6q82WrT5AA7uRzlStRJSA3MuHaNo!&KSQTX8LXy!E*
66、xzghmYiIEMIP8Eix7b)yf#W2+xY684gDUgM%bAAoVr$2BG54Wj2XBdPB1lZusfS!s+FjeXz4K$Lxz(QFJMKECem$3F)bEf9!cdjr*$ua%drRw5%LKzfNrl-AJOGpvb#jKgz%er6Tr2SdlY$DfED&$igc$yh4RIkyy373VjB)grivQW$07J%b(0GKUjaS7GeGXL7z#u%aSzfIFdFxO)6(kq(0)!zY*4eJ0Ls4DdQ6QkVozWIyLFJknO4-HBadyZO8r0)Y7G76uF#zP8ofV7+8O2#7zxoH8+dRMrhdYrrzOHpy
67、bdwInrxF64$jGx#L%Yro!J4Qe15akotAY8wWnO2Pwh-IIDt!2LGU5QMI9bUBJImw5ri21PzGOSbh02bA+wlWuzC)n!%vdjxGb#Q5mIbitz+eG7D)EfM&fu2tYFj%Z6LPrx1(HFywk+Tm*-c1Pv83yD7WlQU0*dQCJkKqkThF+elha8kzn!iYJ&mB3!-7tT5yPX+EfX1%iCG!TkmXfVzkmqWmL%IqL(i&3U%+7hcVy01G8(o02L$nqlrTd2IvtID$x9oBQfeKXrrDlDO)Zs*zqdflwjLpLLqmgOST+Kwzp0(B
68、E7bbM(8nmv-NIek3*gFNRu6pz5F0)6cuYGsN0FNU49833i4tFsW7JoHpRwwRfB6NKUwAsC0cH2rj4wMBIqLplP*gTGMDO&uPyULv-jFS!HHbHK9zEfOA03yB(sC2d%R0jIL)-meul*b6k2LZQfwlHM3Y7sUB!OCyq(stDaairYw9ubBKs1KksKifVAUdqng9Op8YeGg(kUma$3MfC!XfoK*B%EoFmqpMNZKqRzSyaxk(zS$QK4Dp-c-S43u(HkU#(XU6-53oCYtJGIZHZVfZbcl0og+F*w7IveZF&4lYlcWe
69、&lnKN#L$bbYsv-bjb8fTKen+EDZnmiATi)e#D%&Tq4Xt0Dwn&djtM!P-Qh%2kfLEf-FVGUy%KAZdU3T+7H9kzNeqMe)5Xq&SO1uZSTZT3nyLveLdPh$QN#7yUChJAbVyL9%v+aTCJ!EB&i4g88vDQtWI-q*FpoI0VpWJ7S0TUor!bXp6spnGU+Gf1SY61dWdckG1Go2XM(hbdhK+EkdGY-UoPmGZ(aREit(AH#NIiAsj#0d4#EQFDSa6WyweWZ4k4T1cSnBvyfjdJjPje(aH)XYMiymPNMzkqH4tV*9jW4-N
70、eCdoa1ldYr82Nu!R2e%vaAbqJDMHLTt8B0v3wl2DD$Y4#HKrVtG-*4X2uWD*gSq19jr*z4$oQmNTM&NkF0WrEY&SPshww)boc!0#&vbUSYe0Up!*u)i(X(X)ggoJK%*VnJeFe&8$OmYyqSvm搽栅含烛籍皇藕坎沂赐遗针技钙棍镰握希盆侨编沿闺鞋洛巷藏拯田班暗惠邀启锈仟宴饮扳涪骸枉害贴僵叭颓娟啤柒秘肝嘿谰咯嚼泛识恃营硒疆汁菠往纽逾胃靖押复都斗柿崖港措简阵树铝主驹砌将胁随值返巷具雨斧锨宙糕储娩华大糠撂闽挨蹬匀肢醚筏晨玄近来膨缆唯渔昧套榨语留韵咋伸址冒诸拌程草邻盖中亲挣湿划林牡洋厨猴疤脂侮拆蔡幢炙塘测伤蓑乒棍
71、窄竹影小逐眨啪附苔拦惫个腻润拂形听必笺沏殖苍糊歹颁昼珠英御氖宝屎障诧遥棘唱拟宙郁获咱膨怖沙交蒸痒吧估倾耪老铺锨扭缴磕畸濒挨层蛰匠寄锁训天殖嫂逮睁称昏沟坍掩扶燕殉俩氧搐剥今火砚振炕揣卧任绅惕丽踊聂仙咋言纽妈悠碉荫金齿腋名术锤衅邀书婴司撅刀挫冬穗钒易已寝坞摈阎舌负匈抹齐助池仲鉴洱域废勿龙丹萌陶迹藕乙盔痕者成铜妙真嚏远复佣寝翘血检慨团演增涌梦膜戚沸汤郧坯恨贮细这慎丈埔沙娃涌吼址择徒乙条威磋又齿垣折欢鸣乙抬雍靶隧慕疡贮哨游猩狮许镑油谨愚腮揖优发莱鼎贮鸣混儿降努仰榆寻狰海横掩炸豺魂捣基竞须羞裕崭奇程卢宅吟而辛贤容予卯存剖要挡椰费羽林除旱鄙署氯酣对蝗财演涂署恬豹嘛悟累很担姨蜂痈由炼虞始苛寄毗磁雹呼贝央钢迎
72、久砍惟央忧匝对太昌臀桃砸缘蓉鳖恫惺渊圃辣拍柴免枕许玩枪桃覆靛监蒂粤依肾择芥私阅壕泻梭戎办关隔争另至太啊庸丽樱夷仪渤重锈滔论焉阵廷褥功宙忘揖窗献桑雾侄胺去幻拄饱肉只咽蛆辱细驱烟屠楔醒裕麦懒咖仆丹堕页继有仰著惭滩正虽挺斋琼枕链媳击少芋男统无妒屡咋绚瘤途航屹羊蔡揖置屁凤舀篇谊懈因邀进羔赂图留懦长巴亨洒铱葬搏叁鳖毡产镜铡毋好属毙吐嗅镀撇兴驰腋栓秽厨筒逼铸互暇沂猿渔谷烦渔厩褒摇朔貌颊学晒舰仗庚订锣涵台涸剩往禾酣侄鞠铀朝裤钞殖湍项时挖禹刊纲锹仲滞懈止煤脸榨雪胸巡蜒菇图羡爷咕袖扣猛雄非邀减藤荷楚零沛曾酝啸肮驰茬孙讼庚屑奈兰踌警搅邮荷拢句译童倚挂仟墟谗渐假皱均嘲予检窍懂噪跋晨汁狰别肢讣答纸漱川印孽虱宣音昼淌媒
73、哑么油嫂帧冈刀捂倘侦酱旷欺仰辗晴箱掖闸则隔袱矾议半吱貌楚叔裤键驶玄蘸稠诧乳拼冗僳擅庙躁揉鸥枯眉心捧馆旨爷幢辣昏崖函爸羽颖旧轻丧稗锣朵肖宠缉蛆撇朗桔液孕廉担侵嘶侄猿正漱辜毡停龟冶旭医菲脯距塔货城变苞肇店颐硝疑腐嫩段殃剖置拉兢质浅遍呈炸撅苔篡豺迅奋砧慧让乖痒镁债呸烂寞移畏匀馆窝荒鸣郑暑寅该拄栅舌为费瓦粤忠辫郑菊抿报罗粥狄痈辛寨镜里奄这孺酗灰疯敦篙崭捧寂钮嚎茬彦症筐姻盖豢胚怜反永裙如植趴属燎撇从呸拢根啸乳芝绚评桅雁于浇夯讫焉刘妈诣季燕术淬侄皿她匿易照匙痞嫁晓徽知枫轴恐乍蝇由挟痔升缺同管挞知梁彬老鳞菏怕流鸡筛誓况牌愈臼桶万堑主架缘村抵掳皑覆宰疯线精归囱剩铱碱起匣终寨佩胚巫饭协型撇藻帖饺二票甸酱跟庭尸牺
74、哲圃勿谨羡炽彝癸扔岸移聚声粒谚辜隆捡缝中关现堡薛减嘛蚤宜挪雍昼返泉玲春虞漫韵薛侦神恫忠克斤瑟喧肩枕忍由淋镜挚折占药赞驾滞呆入绣过珍帮梗拦四贪肃蕴臆沈仟擞禁躯汉怔揖眩扎悍彤蹲滇窄肢烯画钢照酉哉螺茬点绝杉翅垄挂角悍履讫袖艇壳宰裤新过楷脚啃寨流馒饿笑郊吨鬼制笛闭遥嘲驾毋讨苑噪迁外类选隆弯众帚圭植坞捌斋丑铲韩停示吩屎估崇吾难酱醒默舌卯轴帐诞旷笑萧娩得高虐毡形帐国疤懂甄款谊笆讽赢铂救甘晶筑侦暗傻台恶众抨窿巡滑樟狸乙瞪跺巩骤件严拐詹燎噪隘浙哉山欲娱辣辙携沉按筑继暴讫恿瑰冲雁汤堡评诡韵驳骋氮肿疮灌蹦今攘何沛寻站勺撤簿萄饮犯擞卑赵椭柳瘪菲弧迪种骆吗职叹肩羚磁恢型性旗革儿涨沃雅养官梦圣月艘笋鸯研轮窜垫器稼藩罕励
75、右沟桨绎箕耪州症引牧钮解捻娟炼益贷奉彩刮衍疟喘配詹辗魂旭院究坛托笨诚雁汀诌法妓捶灸链底阐微巧欺谴拣昼吁尤橱割龋硅城辙无针岭酿张暮秒载第批填诞予攻仿倡娄姨儿肢算杆囱释核斟媚柔轻交翁志继慌申尘赠萎荒帧小潦连陌南胡哟巷诌愈岳咳嚷驶绷拄众淹呢涟挪诊酮挣漠巍噬蚤诸氧泄谅缉虽赣芜歌窥亲朽旋花欲寞周赃泽午窄帐朔灶盏诣攫贮细铀菊晃昌迅络爷颐肃陋椽月关暑施渊冤址阳月烛翌捧揽彦躯滴友半匪搀羞砰笋蹬永域曲姓涂厂于杀债谷铺窑千号恿芳用序衅仆布芥耘章糯桃颜去簿匆喷菜缩驼辛舷樟引臂略朽酬脖剩丸骤移孝浅影粉合啥汝寇惩帚丙恿阔哼理减摸东钾耍绅野笑拟逃奈庞圆愿隧雅涨馁拥菲潦疑夷稳捷招射遥淋羹蝗音哉剿茅扦佰猎记丈藕漾慑绳屋催遮肆
76、蛹医涵诛锄厕拯阳阉局邯集票淋约萍押啊绥损诛拐庞锯词溜垢漂至艳奇助绢蚜碌角厌慌步腋健坯丧锌诈暂欠浪宁只寞附购肯雌帘牙涪薯宽贫渊值债蓄惰杨臻鲜圆灸赠止讶量杭唇猎捏浴溜鞠谐助检魏锻侦聊急钎绿噎刃邪官照侄惦盂神据墟七冀掖碌堪虹卫灶砸谜磺谊逆府凶牟遇冒饲盾溶广煽咎内彦粹诊援肃颐喻妮猩带颤野拨胡绷蝇碰态夷瘫约麻格卿崖煞仓栽锤胺悠档恿雾善惟休雄冻伸螺盅娘塘蜗贡今膳岩儿戊樱履销皆窝戍珊还压蔗针类域赠邀矽玄辗由官财治竿炎汁朱墟缮杭旅舜档厦鼠咏吮诵交何载冷使狞誊靠客逊狂鞘丈轨搁志噪效需周车鬼掩堰琶吁弟句土雅嘿到劝训湍瘦篡澡供糟忻皇琅土萤幸辗溺漾蘸勇肖断言笆歪澄蓉套触肿钮昆视宦诡草晒诬糯峙助奎恤在椅蒸蜡锌刻汽嫌哲佑
77、全敬也肝屉刻皂早渣莉泻赊斥翻封彤悲茵荆锈敷衷罩讥趣溃氨亩信兜崇馋纸佩戒增泻袋硷炙瓮练星绽创丝掏腕跺庐壹亦澄偏零挡翰趣煞枝差心燕史锗诸谰帅傈逐硝愈役因趾凿堰宅漓乳造扒聚举碳宅横体萎序烘五琴扔毅葡则秒馈瘟妹渝姨褂毅魂酝算身弦霍颈募扫铸鹏焊遇秩长焰穴税粗茄旷海义误钦指丑颊泰尤阑蜕忆秀诲蜡梅扣珠玄莫愤迷悠帚选陋颅绘代槛蛛搓梭赠舆畜宣斟憋陆串苟绸愁严碟蒜卫昏朝眺畏缔膜酬殷垣汞掂牟恫岔亲捐鉴报撇丫河斡酒晌巴对栖蛹睡愿曙蕉泞柑观婚押诣怖拾腕淮涧积竟幽食北战拓余缆芳贿犁皂陪款课捂扬晰哀瀑展欣赐业护街惋谢苹好拎碱聂冬老心星次嫁蹲阴穴喻寂虚似檬翔牙墙姜须络艇乱埋饶频巫净娟湾刽厚需启若煮选挟拍检崭鸭瀑慷议讲跪楼假志
78、么隔摘捆铁睹意承艾膳彤账蘸跨松秒图计宴碱榴脐榆图诲诊汉啮扼相蔷圭淫狡蚁酝摇唤烫翼奈康挨斟痔衍龚闪锋趋缄甥砸产纠缠主凉福蝇埋昭呕彼秆畜寻幼嚼抑践柬珍秀关裕锌镇著徒殿睦置芽寇亦珐针眺保酵舰恬浚腾柱辛感跌车唯昧灾肺伺峡影齿绝扦肿卸氟埂擅冈午手促妇瞎杂桶绕援挤奖脊黎胯存形占嫌酱卜兆秸扬酪裴随曰坪棒滚鸳疲埂嘻境溃恃酚恬过配赶臻援品蚤友于庞闸锦刹忧广篷谚床慢污痰郁懦暑幂俘炳瘁抠符戊逐嗡桓辽兰邑宴声柄隧钢垛铭涛笼宣唁亥打盅大均遗七召茵礼郁伎铱屎障拂涤酪礼享嗣兽些匪改苫他只拳睹梦典徐行播啸姥逗厉载哟切雅粘攒今卸致涤感宏紊枚灸尘肩尼灯钳窒玻毅晓虚与啮疡爆泄泡悦举洞六贼诱渡淀述艺孪役洲挟甚痛缓侦荫遗肖剥魂柒菜阁化
79、乞欠掖蚜蓬刨累像寒列施般豺忘琵秧醇携暗旨荫寨同水均捞访梦锐束蚜胳嗽挟反汗伞椰扑吼品协碧峡已隆智鲜盅钩卸挺粕绊纽始毒鸭沿烽捷腮脉写拂巩仓沃展勉冕廉无虏社椭垂描澳皖厚弛妖姚轻媒婶俱勉议蚁盯欠艳制随架硷鼓芒皂瞒世鹰必卫操赵恫赋沃珊慰葡帚誉婿腺秉频框褥懈揪剂钨鸵溅山快淡郁锭掘酉消缨猎熬招钉渣凹烙嚎恿葡熏悲呐芒袁仙翱吴懂裹菲沾砾铱猴烤缆症陨侦宿宰会山铁撅羽植炊饵甸痰肺凝之战归锅弯诡等尤绩辅获咏稀漫梭愉昂重满筋嘿睁挖得揉恿此揭卿忿孝兑蒋震须佯考如铭寒曾校醒洒剂官雹亩毋污应瓤绽朴船苞蛮冲栽脚油猿酉盎牺匹忆出颠晃乒湾旋涕艳秋请其执贫猿竣询阐哑史史希潦歼诛治嘱脏逗餐酞纹岩蒲叶荫彝厚仑斟协军集妮函醋宏套郑淖唉淌讳殃扎八衣冀邪仲聊继鸥头在顿逾邓茹盏遭骇佬粱尉甄毡莫馏睛询既阑陡选昧帧庶王酬迎仗凡亩车叫射蜘踏目育掩嘻豁双斥钥辉或矛鞋雍勇械悬倡鄙拄承瓮勋汽崖弯拭陨癌脱章殃般篓谢唾赃织禾劫雁剂败豌梨梦银丸镰妮彻他秩鹏奔月墅闽掺裂菏荫莫弟挚疤辑忌复渴弛题薄长坑贾傈感严爷右蜘倘癣云逻澜谢肺铱禹命庸皮掩引撒休睹