计算机系统基础知识

嵌入式计算机系统概述

嵌入式系统定义: 以应用为中心,计算机技术为基础,软件硬件可裁剪,适应应用系统对功能/可靠性/成本/体积功耗严格要求的专用计算机系统
基本的计算机硬件组成: 运算器/控制器/存储器/输入设备/输出设备
运算器(ALU): 执行算术与逻辑运算
	- 算术逻辑单元
	- 累加寄存器
	- 数据缓冲寄存器
	- 状态条件寄存器
控制器(CU): 指令/时序/总线/中断控制等
	- 程序计数器 PC: 存储下一条要执行的指令
	- 指令寄存器 IR: 保存正在执行的指令
	- 指令译码器: 解析指令代码,生成时序控制信号
	- 时序部件: 产生时钟信号,协调各部件同步工作
存储器: 
	- RAM 
      - SRAM 成本高,容量小,静态功耗大,一般用于CPU寄存器/cache 
      - DRAM 成本低,容量大,静态功耗小,一般用作外部内存,如DDR/SDRAM(DDR) 
    - ROM
        - PROM 一次性写入
        - EPROM 紫外擦除
        - EEPROM 电擦除
        - flash 基于EEPROM
            - nor flash 可直接运行程序
            - nand falsh  擦写快速
    - cache: 位于cpu与主存之间,速度接近cpu时钟频率,当cpu需要获取数据时优先从cache获取,没再从主存获取,所以cache主要为了解决cpu与主存速度不匹配的问题

数据表示

进制转换

a进制转换为b进制,
    - 整数部分a除b, 余数作为第n位的数值,商继续除b,余数作为第n+1位的数值,直至商为0
    - 小数部分a乘b, 整数部分作为第n位的数值,小数继续乘b,整数作为第n+1位的数值,直至小数为0

总结的比较快速的转换规律:
1. 十进制转2/8/16: 大于256部分先对256进行取余法,最后展开为2进制,再从2进制按位数聚合为8/16进制
2. 2/8/16进制转10进制: 按位权展开

嵌入式系统硬件基础

数字电路基础

逻辑电路

- 组合逻辑电路: 任一时刻的输出只取决于该时刻的信号,不含记忆原件
- 时序逻辑电路: 不仅与当前输入有关,还与该时刻电路状态有关,必须包含记忆元器件

数字集成电路

按开关元件的不同,可以分为两类
- 双集型集成电路,采用晶体管作为开关元件 TTL
- 单极型集成电路,采用绝缘栅场效应晶体管 MOS

可编程逻辑器件

FPGA: 现场可编程逻辑阵列, 运行可编程,足够灵活,掉电数据丢失
CPLD: 复杂可编程逻辑器件, 数据保存在存储器中,掉电不丢失,灵活性不高

微处理器基础

计算机的两种基本架构

- 冯诺依曼架构: 指令与数据存在同一个存储器,并使用同一套指令传输,实现相对简单成本低
    代表: ARM/x86
- 哈佛架构: 指令与数据存在各自的存储器,并使用各自的程序总线与数据总线,复杂成本较高
    代表: AVR/DSP

两种基本指令集

- CISC: 复杂指令集计算机, 硬件复杂,指令数多,复杂指令时钟周期长,代码少,编译器优化简单
    代表: x86 
- RISC: 简单指令集计算机, 硬件简单,指令少且简单,适合进行流水线优化,代码多,编译器需要优化工作
    代表: ARM/MIPS/POWER

多核处理器

- 同构多核: 内核相同,地位相等
    代表: intel(酷睿)
- 异构多核: 同构相反,一般主处理器+协处理器
    代表: AMD核显/TI(ARM+DSP)/Xilinx(ARM+FPGA)

异常与中断

- 陷阱(trap): 主动产生的异常,如用户程序系统调用(syscall)内核程序或进行调试
- 中断(interrupt): 分为软中断与硬中断,硬中断处理外部IO等设备,软中断是由软件指令触发
- 故障(fault): 程序运行问题(内存访问,除零等运算错误),发生时进入故障处理程序,如果无法处理执行abort
- 中止(abort): 程序无法继续运行的严重错误情况,如内存损坏/cpu过热等,程序直接停止

模数/数模接口

A/D实现
    - 计数法: 通过计数器关联D/A从0逼近模拟输入电压,当Vo>Vi,计数器的值即为本次A/D转换的数字量,本方法简单但速度慢
    - 双积分法: 利用积分器的公式进行转换与比较换算
    - 逐次逼近法: 类似于计数法,但Nbit逐次逼近寄存器由高位开始比较,当Vo>Vi,本位赋0,这样N位A/D转换只需N个时钟周期完成一次转换

嵌入式硬件设计

电路设计基本步骤

电路设计主要分三个步骤:
    - 设计原理图
    - 生成网格表
    - 设计印制电路板
典型电路设计基本步骤:
    - 了解任务需求
    - 方案选型
    - 按照设计框架进行单元设计
    - 根据电路原理与分析方法,进行参数估算
    - 元器件选择
    - 电路图的绘制

电子电路可靠性设计

可靠性定义:
在规定时间与环境条件下无故障出现的概率,此概率受到工作寿命/具体环境/故障的定义
故障衡量:
- 平均故障间隔时间(MTBF: MEAN TIME BETWEEN FAILURES): 在确定时间内故障率的倒数,通常描述可以修复的设备
- 平均失效时间(MTTF: MEAN TIME TO FAILURES): 通常描述不可修复的设备
- 可用性: 正常运行时间与正常加故障时间的比值, U代表使用时间,D代表故障时间,可用性为 U/(U+D) 
- 可靠性设计: 在有效资源下尽可能提高可靠性
    - 有效的散热
    - 减少高敏感器件使用
    - 尽可能使用可靠性高,质量好的器件
    - 指定采用屏蔽性好或内嵌的测试方法
    - 使用最少的元器件实现
    - 器件级别进行冗余

PCB设计基础知识

PCB可靠性设计
1. 地线设计: 
    - 正确选择单点接地与多点接地
      - 低频(f<1MHz)与受干扰敏感的情况选择单点接地,
      - 高频采用多点接地,避免增加接地阻抗
    - 数字地与模拟地分开,因为数字电路工作时会产生快速脉冲,导致对地电流产生较大变化,对于模拟电路来说这种是噪音干扰
    - 尽量加粗地线,至少能承受3倍运行电流
    - 合理接地构成闭环环路,例如射频收发的高频信号需要低阻抗的路径,围绕射频电路区域形成一个接地环,或者在多层 PCB 中通过过孔将不同层的接地线连接成闭环
2. 电磁兼容设计
    - 选择合适的导线长度,尽可能短以减少电感
    - 正确的布线策略
      - 最好采用井字网状结构
      - 减少导线不连续性,如导线宽度不要突变
      - 时钟信号与地线靠近
      - 信号线可以设置接地的导线
    - 抑制反射干扰,尽可能缩短导线长度与采用慢速电阻,必要时进行阻抗匹配 
    - 去耦电容使用
    - 合适的PCB大小与元件布置

嵌入式系统软件基础知识

嵌入式软件基础

嵌入式软件特性

1. 资源受限
2. 开发难度大,要对编译器,编程语言,操作系统有深刻了解,底层软件开发还需要对软硬件有扎实基础,开发环境与运行环境不一致
3. 实时性与可靠性要求高,需要在确定的时间内对外部事件做出响应,对于重要的领域比如航天,核电站软件不能出错,可靠性十分重要
4. 要求存储固化,大部分为了加快启动与执行速度,大部分软件程序直接存在存储器芯片或单片机内部

嵌入式软件体系

1. 无操作系统的情形
    - 循环轮转方式: 在一个循环中不停执行任务,此方式简单但不能异步处理,并发处理
    - 前后台系统: 在循环轮转方式上加入中断,中断作为前台负责处理异步事件,打断当前的执行,后台负责掌管软件硬件资源分配,任务调度等,此方式实时性相对循环轮转方式要高,但任务具有同样的优先级,任务处理仍然是先进先出的处理方式,对实时性要求很高难以处理
2. 有操作系统的情形
    - 应用软件在操作系统基础上编写,不直面底层硬件
    - 提高可靠性,运行时起码保证系统不崩溃,崩溃有良好的自愈能力
    - 提升效率,应用程序可以按软件工程的思想分多个任务模块
    - 利于扩展与移植,应用不依赖特定的硬件平台,适配驱动,移植操作系统,软件基本不需更改即可复用

嵌入式操作系统概述

嵌入式操作系统特性

1. 非通用型操作系统
2. 性能与实时性有严格限制
3. 功耗,成本,可靠性是影响设计的重要因素
4. 占用资源少,适合有限存储空间的场景
5. 可针对功能进行裁剪适配

操作系统的分类

1. 按功能分类
    - 单用户OS
    - 批处理OS
    - 实时OS
    - 分时OS
    - 网络OS
    - 分布式OS
2. 按类型分类
    - 商用系统,如VxWorks
    - 专用系统,为定制的
    - 开源系统,如uC/OS,linux
3. 按响应时间
    - 实时OS
    - 非实时OS
4. 按软件结构
    - 单体结构,内核集成许多组件(驱动,中间件等),模块直接相互调用
    - 分层结构,其内核与单体结构类似,但功能划分不同层次,每个层次向上提供一组API接口
    - 微内核结构,内核只保留基本的任务调度与内存管理功能,组件可以动态添加,易扩展,安全,移植性强等,但由于内核与组件通信是消息传递,而不是函数调用,开销会更大

任务管理

单道与多道程序

1. 单道程序: 完成一个程序才能开始另一个程序,实时性很低
2. 多道程序: 一个程序可以让出CPU给其他程序,优化了程序在IO操作等等待行为中占用CPU,实时性与CPU利用率很高

进程,线程和任务

1. 进程: 正在运行的程序
    - 动态性: 运行状态不断变化,如PC指针与通用寄存器,另外在程序调用时,堆栈也会变化
    - 独立性: 进程上下文数据与状态是独立的,互不影响
    - 并发性: 宏观上看进程是并发运行的,虽然在微观上(单核)CPU只能运行一个进程,但进程通过顺序使用CPU宏观上实现并发
2. 线程: CPU调度的最小单位
    - 内存地址,数据,代码,文件等是共享的,而且通信与交流很方便,效率很高
    - 有小部分不是共享资源,比如上下文数据,栈
3. 任务: 不同系统不同解释,
    - VxWorks,uU/OS-II等认为是线程
    - Linux认为是进程

任务的实现

1. 任务创建发生的主要情形
    - 系统初始化,如内核在初始化时,可能会创建与用户交互的前台任务,以及在后台运行的时间统计/系统状态检测等
    - 任务运行过程中
    - 用户提出的请求
2. 任务创建的实现
    - fork 分配与父进程一样的内存空间,并复制任务的代码与数据,以子进程去执行新任务,常用于服务器程序,多任务处理等
    - exec 执行新的任务替换当前任务
    - spawn 与fork类似,在某些编程语言或环境中,能够方便的处理子进程的输入输出,传递参数等
3. 任务的状态
    - 运行 任务占用当前CPU
    - 就绪 准备运行的任务,分配到CPU就能运行
    - 阻塞 任务主动或被动的让出CPU,等待某个事件发生,例如IO操作,任务同步等
4. 任务的切换
    - 将当前任务上下文信息保存在当前任务的TCB中
    - 当前任务变为阻塞状态
    - 通过一定的调度策略从就绪任务中选择一个任务执行
    - 将新任务状态修改为运行状态,将其TCB恢复上下文环境

任务的调度

1. 任务调度的时机
    - 任务创建
    - 任务结束运行
    - 任务发生阻塞
    - 任务IO操作完成/获取信号/时钟中断等
2. 调度方式
    - 不可抢占式 不会因为IO,时钟中断等原因让出CPU,只有因为其主动让出CPU,才会运行调度器
    - 可抢占方式 任务运行时,调度器可以打断并运行新的任务
3. 调度算法指标与分类
    - 算法指标
        - 响应时间 任务在就绪队列里等待的时间
        - 周转时间 任务提交到完成的时间
        - 调度开销 任务调度所需的时间,空间开销
        - 公平性 任务之间得到的CPU时间应该相近
        - 均衡性 使用效率,尽可能使CPU,IO资源忙起来
        - 吞吐量 单位时间完成的任务数
4. 任务调度算法
   - 先来先服务(FCFS)
   - 短作业优先(SJF)
   - 时间片轮转(RR)
5. 任务同步与互斥
    - 任务互斥: 因为两个或两个以上任务对同一个共享资源操作而产生的竞争条件
        - 关闭中断实现,简单,但会影响系统的实时响应能力,因为其他非互斥的任务也可能因中断被关闭而无法及时处理
        - 繁忙等待法,在进入临界区前循环检查是否满足条件,不满足原地等待,这种浪费大量CPU时间
        - 信号量,通过设置信号量数量,允许多个任务同时共享资源,当任务未能获取资源,任务被阻塞让出CPU给其他任务
    - 任务同步: 任务间需要以某种时序或配合完成特定的工作
6. 任务间通信
    - 邮箱,只能传递单个消息,其状态只有空或满两种状态
    - 消息队列,可以传递多个消息
    - 管道,UNIX首创,以文件系统为基础,两个任务间连接一个共享的文件

存储管理

实模式与保护模式

1. 实模式: 只有一个物理地址空间,所有任务共享除了栈与运行上下文以外的空间,优点是简单,开销确定,缺点是没有存储保护,安全性差,大多数传统嵌入式都是此种方式
2. 保护模式: 通过MMU硬件完成由逻辑地址到物理地址的映射,系统内核与任务间地址独立,具有存储保护,每个任务只能访问自己的地址空间,共享的空间也需按规则访问

分区存储管理

1. 固定分区存储管理: 启动时分配,固定,优点是管理,分配与回收简单,缺点是利用率不高,易产生内存碎片,分区固定灵活性差
2. 可变分区存储管理: 动态变化内存大小数量,内存利用率高,但管理复杂

地址映射

1. 静态地址映射: 直接修改对地址访问指令代码,对逻辑地址加相对偏移获得实际物理地址,不需要MMU等硬件支持,缺点灵活性差
2. 动态地址映射: 通过硬件的基地址寄存器,逻辑地址加上基地址获得物理地址

页式存储管理

1. 基本原理: 将内存分页,程序运行在若干不一定连续的页面
2. 地址映射
    - 通过逻辑地址计算得到页号与页面内的偏移地址
    - 通过页表获得物理地址页面
    - 物理页号*页面大小+偏移地址 = 实际物理地址

虚拟内存管理

1. 在页式内存管理的基础上增加请求调页与换页的功能,当运行时指令或数据不在内存中,向系统发出缺页中断请求,将外存相应页面调入空闲页面,如果没有空闲页面,通过置换算法选择一页进行替换

设备管理

设备控制器访问

1. I/O独立编址: 为每个设备寄存器分配独立的设备端口地址,与内存访问不一样的指令形式
2. 内存映射编址: 为每个设备寄存器映射为内存地址,与内存访问一样
3. 混合编址: I/O独立编址与内存映射编址结合

I/O控制方式

1. 循环检测方式: 循环检测设备状态,一直等待满足条件才继续使用
2. 中断驱动方式: 通过设备引起中断处理数据,但需要频繁引起中断
3. DMA方式: 通过DMA处理内存与设备的I/O数据,不占用CPU,也不会频繁引起中断

I/O软件

1. 中断处理程序: 与驱动程序协同合作,I/O操作完成后唤醒被阻塞的驱动程序
2. 驱动程序: 处理上层抽象请求,设备的具体实现细节
3. 设备独立的I/O软件: 通用的输入/输出功能,为用户提供统一的访问接口,一般包括在系统内核中
4. 用户空间的I/O软件
    - 与用户链接的库函数,如C标准库中的IO相关库函数
    - Spooling,驱动程序与用户程序间的传声筒,为用户程序虚拟一个设备,提供高速的IO,为独占的实现共享

文件系统

概述

1. 由存储和管理文件信息的软件,被管理的文件,文件系统的数据结构组成

文件系统的实现

1. 数据块: 文件一般由无结构的字节流组成,将字节流拆分同样大小的逻辑块,每个逻辑块对应不同的物理块中
2. 文件的实现
    - 文件控制块 FCB
        - 文件属性信息: 文件类型,长度,修改时间,访问权限等
        - 文件存储信息: 文件的存储位置等
    - 文件的物理结构
        - 顺序存储: 在物理地址上按顺序存储,适合不需要经常改动的大型文件,缺点是容易产生碎片,文件也不能动态变化
        - 链式存储: 通过指针将各个物理块连接起来,增加或删除只需要修改指针关系即可,适合需要大小动态变化的文件,缺点是随机访问需要便利链表,时间不确定
        - 索引存储: 为文件的逻辑地址到物理地址建立一个线性的索引表,通过访问索引表快速访问物理地址,适合需要快速的随机读写场景,缺点不适合大量小文件存储,插入与删除也需要频繁修改索引表

嵌入式系统设计与开发

概述

特点

1. 需要交叉编译工具
2. 需要仿真手段进行调试
3. 开发板作为目标机的原型或调试载体
4. 可利用的资源有限
5. 需要与硬件打交道

宿主机与目标机

1. 宿主机: 用于开发嵌入式系统的计算机
2. 目标机: 运行嵌入式程序的实际环境,
3. 宿主机与目标机的连接
    - 物理连接: 通过物理线路连接在一起,常用有串口/网口/在线调试(OCD)方式(如JTAG/BDM)等
    - 逻辑连接: 按某种通讯协议进行连接 
4. 调试和调试工具
    - 直接测试法
    - 调试监控法
    - ROM仿真法
    - 在线仿真器法
    - 片上调试法
    - 模拟器法,适合软件模型验证

软件开发

软件设计

1. 软件架构设计原则
    - 抽象: 提取主要特性与属性,从具体事务通过封装来忽略细节
    - 信息隐藏: 包括局部化设计与封装设计
      - 局部化设计: 将处理的操作与实现限制在局部的组件,尽量少依赖于其他的组件
      - 封装设计: 对外的接口应当简单且统一
    - 强内聚与低耦合
      - 强内聚: 组件内的功能是强相关的,一起组合实现特定功能
      - 低耦合: 组件间的特性无关或弱关联,组件间保存独立,利于未来的修改,复用
    - 关注点分离: 关注点即是软件中易变的部分,如参数调整或驱动配置
    - 模块控制与作用范围: 模块的作用范围应在其控制范围之内,例如事件记录不应超出控制范围,作用到不相干的通信模块去
2. 软件设计方法
    - 基于功能分解的设计
        对功能总体设计,对主要功能进行分解,最后对子功能进行详细设计,适合需求明确,稳定的场景 
    - 基于信息隐藏的设计
        将数据与实现细节隐藏在内部,对外只提供必要接口,适用于维护性/扩展性要求高的场景 
    - 基于模型驱动开发的设计
        以模型为核心,先建立系统的抽象模型,在根据模型生成代码,模型可以是业务/数据模型,例如可以用UML/类图/流程图等描述模型,适合需求稳定明确,规模大,要求高质量的场景

特性设计技术

1. 实时性的设计
    - 合理划分实时与分时任务,例如对于信号处理的翻译/传递/应答是实时,而在运行时的故障处理/信息输出可以是分时的
    - 合理划分实时任务
    - 优化执行效率,如减少临界区占用时间,采用经典高效算法等
2. 可扩展性的设计
    - 硬件驱动管理机制: 对底层各类驱动进行封装,上层通过标准的接口访问
    - 模块化设计
    - 可定制的设计
      - 可裁剪性
      - 可配置性  

软件移植

无操作系统的移植

1. 基于模块化的软件结构移植 (应用程序->输入/输出模块->底层硬件)
    在移植时只需要修改硬件相关的输入输模块实现,如统一的 GPIO 控制函数 hal_gpio_set(),其API不用变动 
2. 基于硬件抽象层的软件结构 (应用程序->输入/输出模块->硬件抽象层->底层硬件)
    相对于基于模块化的软件结构多了硬件抽象层,移植时需要修改的代码更少,只需修改硬件抽象层的实现,其他可以不变

有操作系统的移植

其软件结构分为硬件驱动层/操作系统层/中间件层/应用程序,移植主要是对bootloader/硬件驱动/系统中硬件相关部分进行修改

应用软件的移植

1. 软件设计上要层次化与模块化,层次化是纵向的,下层为上层服务,模块化是横向的,模块间互不依赖,相互独立
2. 在操作系统与应用间加操作系统虚拟层,对于新的操作系统只需要修改这一层次,例POSIX标准,用open()替代Windows的CreateFile()
3. 尽量不调用操作系统特定的函数
4. 数据类型自定义
5. 不可移植的部分局域化,例如通过用宏定义/函数封装其实现,分类集中在不同的文件

嵌入式程序设计

程序设计语言基础

程序设计分类

1. 命令式程序设计语言,描述的程序运行的过程,步骤,如C/Pascal
2. 面向对象的程序设计语言,新增类与对象,封装,继承,多态的特性,如C++/Java
3. 函数式程序设计语言,函数与其数据结构就是程序,如LISP
4. 逻辑型程序设计语言,以形式逻辑作为基础的语言,如PROLOG

汇编语言程序设计

汇编语言程序

1. 汇编语言程序中的指令
    - 指令语句: 编译后能产生对应机器代码,如MOV,ADD,SUB等
    - 伪指令语句: 不产生机器代码,在汇编时其工作就完成,以下以ARM汇编为例
        1) 常数定义伪指令: X EQU 50    # 定义标识符X为50     
        2) 存储定义伪指令: str DCB "TEST" # 分配一段地址并初始化,str为起始地址
        3) 汇编控制伪指令: 条件判断指令IF/ELSE/ENDIF,循环执行指令WHILE/WEND
        4) 开始伪指令: 如ENTRY伪指令代表程序的入口点
        5) 结束伪指令: END通知汇编器到源程序末尾  
    - 宏指令语句: 将程序段定义为宏,在相应程序引用宏即相当于引用对应程序段

程序编译

1. 词法分析: 处理源程序的字符流单词,进行初步划分归类
2. 语法分析: 在词法分析的基础上进行分析,得到语句的结构并生成语法树
3. 语义分析: 对语法树基础上,进行类型检查/作用域检查等
4. 中间代码生成: 介乎于源程序与目标机器语言的形式
5. 代码优化: 对中间代码进行优化,提升目标代码的质量     

嵌入式软件测试

嵌入式软件测试技术

测试过程

1. 测试需求分析
    - 明确需要的测试类型及测试要求,测试类型包括功能与性能测试,测试要求包括状态/接口/数据结构/设计约束等
    - 细化文档来源,建立测试与需求文档的追踪关系
    - 挖掘潜在的需求,如跟用户/产品经理等沟通获得潜在的需求与边界约束
    - 确定每项测试的优先级,充分性,测试覆盖度
2. 测试策划
    - 根据测试种类与需求,安排人力/硬件/软件/时间等资源
    - 风险应对管理,对于可能出现的如需求变更/人员变动/技术难题等风险,提前进行风险评估并安排处理对策,比如技术难题,可能需要提前安排技术调研或请求外部支持
    - 制定测试计划文档,明确测试范围/测试策略/进度安排/资源分配/风险与应对措施等,作为测试项目的指导文件
3. 测试设计与实现
    - 环境配置细节,详细描述测试前的软件/硬件环境,其搭建方法与步骤
    - 测试层次与单元划分,根据项目特点与需求划分层次,如单元测试/集成测试/系统测试/验收测试,例如单元测试最小测试单元为(如函数或类)进行测试,系统测试侧重于模块之间的接口与交互测试
    - 测试数据设计原则,阐述测试数据的原则,如有效性/代表性/边界值覆盖/异常值覆盖等,以及测试数据的维护与管理,便于后续复用与准确
    - 测试用例设计方法,详细说明编写测试用例采用的方法,等价类划分法/猜错法/边界值分析/因果图/决策表等
    - 测试输出预期值的确定方法,例如根据需求文档/经验等确定预期值,同时考虑不同情况下的预期值(如正常情况/边界情况/异常情况等)
    - 测试结果的处理流程,包括如何记录测试结果,对比结果与预期值,如何进行结果分析与统计等
4. 测试执行
    - 缺陷管理流程,详细说明发现缺陷后的处理,包括如何记录缺陷报告(复习步骤/预期结果/实际结果/发现环境等),缺陷如何分类与优先级划分,缺陷的跟踪与回归测试
    - 测试用例调整,在测试过程中对发现用例存在不完善或不完整,进行调整与补充
5. 测试总结 
    - 测试指标统计与分析,对测试进行总结,统计一系列指标,如测试用例执行率/覆盖度/缺陷率等
    - 经验总结与文档归档

测试方法

静态测试
通过阅读代码进行代码审查与代码走查,不需运行程序,发现错误即定位错误
动态测试
1. 黑盒测试: 不需了解内部原理,按照功能需求测试输入输出是否符合要求
    - 等价类划分法: 从等价类选取有代表性的测试用例,减少用例数同时保证覆盖度
    - 边界值分析: 选取边界值进行测试
    - 判定表: 分析输入输出的逻辑关系,并整理成判定表,清晰表达逻辑
    - 因果图: 分析输入输出的因果关系生成因果图
    - 猜错法: 依据经验与直觉,猜测错误的地方
    - 正交实验法: 从数据中挑选具有代表性的测试用例
2. 白盒测试: 可以看到程序内部实现,测试程序每个语句/条件
    - 控制流测试
      - 语句覆盖 每条语句都被执行到至少一次
      - 条件覆盖 每个判定的条件至少出现一次true与false
      - 分支覆盖 每个判定至少出现一次true与false
      - MC/DC(修改条件/判断覆盖) 每个测试修改每个条件都独立影响最终结果
3. 灰盒测试: 结合黑盒与白盒测试, 适合于系统或配置项测试阶段
测试类型
1. 单元测试
2. 集成测试
3. 配置项测试
4. 系统测试
Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐