第一题

某企业大型配送控制中心一般采用自动化方式存取仓库内的货品,配送控制中心对货品的存取由两部分构成:其一,配送控制中心管理和调度多台配送车;其二,配送车根据指令从仓库货架上存取货品。

下图为某企业大型仓库货品存取示意图。图中配送车上安装有智能控制设备,通过视频接口接受图像数据,实行对货架位置的定位识别,然后将识别信息发送到配送控制中心。配送控制中心向配送车发送控制命令,将配送车上的货品放置到指定的货架位置,或从指定的货架位置上取出货品,装载到该配送车。

【问题1】

假设图1-1中的智能设备采用8051微处理器,该微处理器的定时器主频为12MHz。

该智能设备中的数据采集周期分别为10ms、15ms、1s,请给出:

(1)设备中定时器应设置的最大计时单位;

(2)8051定时器计数寄存器的初始值;

(3)若8051采用外部时钟接入方式,请完成下图中的连接方式。

解析:

(1)设备中定时器应设置的最大计时单位

(2)8051定时器计数寄存器的初始值

(3)若8051采用外部时钟接入方式,请完成下图中的连接方式

8051 的定时器 0/1 可以工作在 外部计数模式(即 C/T=1),此时 T0 或 T1 引脚上的外部脉冲被计数,脉冲周期由外部信号决定。

若采用外部时钟输入,需将 C/T 位设为 1(选择计数器模式),并通过 T0(P3.4)或 T1(P3.5)引入外部脉冲。图 1-3 应画出:外部时钟信号接到 T0 或 T1 引脚,配合 GATE 等控制位的连接(GATE=0 时,TRx 直接启动计数;GATE=1 时,还要 INTx 引脚为高电平才能启动)。

由于题干没给具体外部信号,但连接方式应是:

    外部时钟信号接至 P3.4/T0 或 P3.5/T1

    根据需要选 GATE 是否由 INTx 控制启动,但一般题目默认简单启动(GATE=0),只需 TRx=1 就计数

连接图示可示意为:

    外部时钟源 CLKextCLKext​ → T0 引脚

    相关控制位在程序中设定

【问题 2】

根据下图所示的配送车取货的工作过程示意图,得到图 1-4 所示的配送车取货软件流程图,请在图中的_(n) 处填入合适的内容。

解析:

(1)分析取货指令

(2)根据位置信息定位

(3)到达目标位置吗?

【问题3】

按照你对8051微处理器的理解,填写表1-1中的(1)~(5)空格, 完成表中给出的5种寻址方式的指令格式。

表: 8051寻址方式

注:

MOV:将存储器的内容取到累加器中

A:累加器

Ri:通用寄存器

PC:程序计数器

DPTR:间址寄存器

解析:

根据 8051 微处理器的指令格式,表中所列各寻址方式的正确填写如下:

(1)直接寻址
    MOV A, 30H(或任意直接地址,如 direct)
    对应 (1):direct(例如 30H)

(2)寄存器寻址
    MOV A, R0(或 R1~R7)
    对应 (2):R0(或 Rn)

(3)寄存器间接寻址
    MOV A, @R0(或 @R1)
    对应 (3):@R0(或 @Ri)

    立即寻址
(4)MOV A, #30H(或 #data)
    对应 (4):#data(或 #30H 格式)

(5)变址寻址
    MOVC A, @A+PC(或 MOVC A, @A+DPTR,题中已写 +PC)
    对应 (5):@A(即 MOVC A, @A+PC 中的 @A)

第二题

阅读如下有关嵌入式软件测试的论述,回答问题1至问题3,将解答填入答题纸的对应栏内。

某嵌入式软件主要用于控制飞机起落架。飞机起落架的可靠性直接关系着机载人员的人身安全。根据载机设备对软件可靠性规定,一般将软件分为3级:关键级软件、重要级软件和一般软件。由于该嵌入式软件被定义为关键软件,规定按关键级软件进行测试。

【例题1】

请根据测试规定,简要阐明语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖的含义。

语句覆盖
设计若干测试用例,使得程序中的每条可执行语句至少被执行一次。
优点:简单。
缺点:覆盖准则弱,可能遗漏分支逻辑错误。

判定覆盖(分支覆盖)
设计测试用例,使得每个判定的真分支和假分支都至少执行一次。
覆盖了分支结果,但不一定覆盖每个条件的所有取值。

条件覆盖
设计测试用例,使得每个条件的可能取值(真/假)至少出现一次。
注意:不一定满足判定覆盖。

判定/条件覆盖
同时满足判定覆盖和条件覆盖,即每个判定的所有可能结果都出现一次,且每个条件的所有可能结果也都出现一次。
但仍可能遗漏条件的组合情况。

条件组合覆盖
设计测试用例,使得每个判定中所有条件的各种可能组合都出现至少一次。
是逻辑覆盖中覆盖程度最高的。

【例题2】

根据本题所示的软件关键级别,回答该软件需要做哪几项覆盖测试?规定的覆盖率指标是多少?假如是一般级软件,应做哪几项覆盖测试?

根据常见航空/嵌入式关键软件标准(如 DO-178B/C),不同软件等级(A级为关键,B级为重要,C/D/E 为一般)有不同结构覆盖要求:

    关键级软件(A级):

        结构覆盖要求最高,通常需要 修改条件/判定覆盖(MC/DC)。

        若题目选项里没有 MC/DC 而只有经典五类覆盖,则选 条件组合覆盖 为最高要求。

        覆盖率指标:100%。

    一般级软件:

        可以只需要 语句覆盖 或 判定覆盖 加上一些其他分析。

        若题目没有明确区分更细的等级,则“一般级”按题中“一般软件”定为:语句覆盖 + 判定覆盖(或仅语句覆盖),覆盖率指标可能是 100% 或根据标准降低要求,但结合本题答案格式,一般软件也要做到 100% 语句覆盖。

【例题3】

在软件单元测试中,重要测试对象是软件模块,假如被测程序中有多处调用了其他过程代码,测试中应怎样处理这些功能的引用?软件的性能测试在测试工作的哪个阶段进行?

第一问:

    单元测试时,如果被测单元调用了其他过程(函数/子程序),一般用 桩模块(Stub) 来代替被调用的过程。

    桩模块模拟被调用过程的功能,可以返回指定的数据,以便隔离被测单元、测试其逻辑。

第二问:

    性能测试通常在 集成测试阶段 或 系统测试阶段 进行。

    单元测试阶段通常不进行性能测试,因为功能未完整集成,环境不足以反映真实性能。

    不过具体到本题,常见软件测试流程中:性能测试在系统测试阶段进行。

第三题

某计算机中断系统有4级中断I₁、I₂、I₃和I₄,中断响应的优先次序为I₁→I₂→I₃→I₄,即先响应I₁,再响应I₂,……,最后响应I₄。每级中断对应一个屏蔽码,屏蔽码中某位为"1"表示禁止中断(关中断),若为"0"则表示允许中断(开中断)。各级中断处理程序与屏蔽码的关系如表所示。

【问题1】

若 ti 时刻 I1、I2 和 I4 级同时产生中断,在各中断处理完毕后,tj​ (ti​<tj​) 时刻发出 I3 级中断申请,CPU 为 I3 服务时,I1 级发出请求,在 CPU 为 I1 服务时,I2 级发出请求。请参照下图所示的格式,画出 CPU 的运行轨迹。

解析:

(1)初始条件分析

中断系统有 4 级中断 I1,I2,I3,I4,响应优先级是 I1>I2>I3>I4(即 I1I最优先)。
屏蔽码:

    I1​ 的屏蔽码:1111→ 关所有中断

    I2的屏蔽码:0111 → 只允许 I1​ 中断(I2 执行时若 I1 来,就中断它)

    I3​ 的屏蔽码:0011 → 允许 I1,I2​ 中断(I3 执行时若 I1​ 或 I2​ 来,就中断它)

    I4​ 的屏蔽码:0001 → 允许 I1,I2,I3 中断(I4​ 执行时若 I1,I2,I3​ 来,就中断它)

注意:屏蔽码是在中断处理程序内设定的,决定了在它执行期间允许哪些更高级的中断。

第一段时间:ti 时刻 I1,I2,I4 同时请求

响应优先级是 I1>I2>I3>I4,所以:

    ti 时,同时有 I1,I2,I4请求,先响应 I1,进入 I1 程序。

    I1 屏蔽码 1111,意味着关所有中断,所以 I2,I4挂起。

    I1执行完,返回时检测到还有挂起的 I2 和 I4,这时 I2​ 优先级高于 I4​,所以先响应 I2。

    进入 I2​ 程序,I2​ 屏蔽码 0111,只允许 I1​ 中断(但此时 I1​ 刚结束,没有再来 I1​),所以 I2​ 执行期间不被中断,直到完成。

    I2 结束后,检测到还有 I4​ 挂起,进入 I4​ 程序。

    I4 屏蔽码 0001,允许 I1,I2,I3​ 中断,但当前没有 I1​,I2​,I3​ 请求,所以 I4​ 执行完。

所以第一波中断 I1,I2,I4I 处理完成,次序:
I1→I2→I4

无嵌套(因 I1​ 关中断,I2​ 时无 I1​,I4​ 时无 I1,I2,I3I打断)。

tj​ 时刻 I3 请求

当 I4 结束返回正常程序后,在 tj​ 时刻 I3​ 请求。

CPU 响应 I3​。

CPU 为 I3​ 服务时,I1​ 请求

I3​ 的屏蔽码是 0011,允许 I1​,I2​ 中断。

所以 I1​ 请求(比 I3​ 优先级高)发生时,立即中断 I3​ 的执行,进入 I1​ 程序。

 CPU 为 I1​ 服务时,I2​ 请求

I1​ 的屏蔽码是 1111,关所有中断,所以 I2​ 请求此时不会被响应,只能挂起。

I1​ 执行完,返回后,检测到挂起的 I2​ 和中断的 I3​ 都未完成。
不过 I3​ 是被中断的,必须等 I1​ 返回 I3​ 执行,但在 I1​ 返回时,中断返回点是在 I3​ 程序内,但返回后 I3​ 会被重新执行(因为是恢复现场),此时已无 I1​ 请求,但 I2​ 请求存在。

所以 I1​ 结束后,恢复 I3​ 前,系统会先响应更高优先级的挂起中断 I2​ 吗?

这里要明确:在 I1​ 返回后,

    硬件会自动检查比当前优先级(I1​ 返回时回到 I3​ 的执行)更高或同级的挂起中断,按优先顺序响应。

    当前返回点是 I3​ 内部,I3​ 优先级低于 I2​,但 I2​ 优先级高于 I3​,所以从 I1​ 返回到 I3​ 程序之前,会先响应 I2​(如果 I2​ 挂起且未被屏蔽)。

    当前屏蔽码是 I3​ 的 0011,允许 I1,I2​ 中断。

所以:

I1​ 完成 → 返回 I3​ 时,有 I2​ 挂起且优先级高于 I3​,于是立即响应 I2​,嵌套在 I3​ 内(I2​ 屏蔽码 0111),此时 I3​ 被二次挂起(准确说是仍然挂起没执行完)。

I2​ 执行完后,返回 I3​,I3​ 继续执行到结束。

我们按横轴时间从左到右,中断请求和处理过程如下:

    开始正常程序,ti​ 时 I1​,I2​,I4​ 同时请求 → 响应 I1​ → 执行 I1​ 完 → 响应 I2​ → 执行 I2​ 完 → 响应 I4​ → 执行 I4​ 完 → 回正常程序。

    正常程序到 tj​,I3​ 请求 → 响应 I3​ → 执行 I3​ 期间,I1​ 请求 → 嵌套 I1​ → I1​ 执行期间,I2​ 请求(挂起) → I1​ 完 → 返回 I3​ 前,检测到 I2​ 挂起且优先级高于 I3​,立即响应 I2​ → 执行 I2​ → 返回 I3​ → 继续 I3​ 到结束 → 回正常程序。


其中第一次 I1, I2, I4 是顺序处理,无嵌套;第二次 I3, I1 嵌套,I1 时 I2 挂起,I1 结束后 I2 嵌套到 I3(即 I2 在 I3 内部执行)。

按照题干图例格式,嵌套的竖线应表示:

    I3 开始时画一个中断请求的起点(竖线),然后 I1 嵌套在 I3 内(画一个从 I3 左边界到 I3 执行再向下到 I1 的弧线,表示打断),I1 的屏蔽码 1111 导致 I2 只能挂起(在 I1 内部画 I2 请求标志线在 I1 范围内,但不嵌套到 I1,而是等 I1 结束,从 I3 被打断点再进 I2)。

自己实现图形绘制,但运行轨迹结构就是:

时间轴:

    正常 → 进入 I1 → 进 I2 → 进 I4 → 返回正常

    正常 → 进 I3 → 进 I1(嵌套,I1 内收到 I2 请求但被屏蔽)→ 返回 I3(此时进 I2 嵌套在 I3 内)→ I2 完回 I3 → I3 完回正常

【问题 2】

若将中断优先次序设置为 I1 → I4 → I2 → I3,即先响应 I1,再响应 I4,再响应 I2,最后响应 I3。请重新设置各级的屏蔽码,填写下表 。

解析:

题目新指定的中断响应优先级(即硬件排队优先级)改为:
I1→I4→I2→I3

意思是:硬件排队电路会先响应 I1​(最高),然后 I4(次高),然后 I2(第三),然后 I3​(最低)。

屏蔽码的作用是:在某个中断处理程序内部,如果来一个更高级的中断(按新优先级定义),CPU 是否允许它打断当前程序。


规则:屏蔽码某位为“1”表示禁止该位对应的中断(关中断),为“0”表示允许中断。一般写屏蔽码时,某中断程序的屏蔽码应该禁止所有比它优先级低的中断,允许所有比它优先级高的中断。

屏蔽码设计原则

对于中断处理程序 Ix​,它的屏蔽码中的第 y 位(对应 Iy​ 中断)的值应该:

    如果 Iy​ 的优先级 高于 Ix​,则允许中断,即屏蔽码该位 = 0。

    如果 Iy​ 的优先级 低于或等于 Ix​,则禁止中断,即屏蔽码该位 = 1。

(因为如果 Iy​ 优先级低或相等,在 Ix​ 中不应被响应,避免同级嵌套或低优先级打断高优先级。)

按新优先级确定屏蔽码

优先级(高→低):I1>I4>I2>I3​。

(1) 中断处理程序 I1

    I1 优先级最高,比它高的没有,所以它对 I4,I2,I3​ 应该禁止(1),对自身禁止(1,因为同优先级一般不嵌套)。
    屏蔽码 1111。

(2) 中断处理程序 I4

优先级:I4​ 比 I1​ 低,比 I2,I3​ 高。

    对 I1​:比它高 → 允许 (0)

    对 I4​:自身 → 禁止 (1)

    对 I2​:比它低 → 禁止 (1)

    对 I3​:比它低 → 禁止 (1)

所以 I4 的屏蔽码  0111。

(3) 中断处理程序 I2​

优先级:比 I1 低,比 I4 高,比 I3 高。

    对 I1:允许 (0)

    对 I2:自身禁止 (1)

    对 I3:禁止(因为比它低)(1)

    对 I4:允许(因为 I4 优先级比 I2 高)(0)

所以按列顺序 (I1,I2,I3,I4):
I1:0, I2:1, I3:1, I4:0 → 码 0110

(4) 中断处理程序 I3I3​

优先级最低,比它高的有 I1, I4, I2。

    对 I1:允许 (0)

    对 I2:允许 (0)

    对 I3:自身禁止 (1)

    对 I4:允许 (0)

按列顺序 (I1,I2,I3,I4):
I1:0, I2:0, I3:1, I4:0 → 码 0010

第四题

在实时系统中,许多控制软件需要将数据封装到一个数据结构中,以节省存储空间。对于位操作,使用汇编语言实现其访问比较容易,但会增加编程难度,因此目前普遍采用 C 语言实现。使用高级语言编程要特别注意结构的存储格式以及编译器的特性。本题所使用的编译器对变量按声明顺序分配地址。分析下图所示的 C 语言代码,回答如下问题。

typedef struct

{

    int A : 16; //按 16 位字对齐;

    char B : 8;

    char C : 8;

    char D : 8;

    char E : 8;

    int F; //占 16 位并按 16 位字对齐;

}

radartype;

typedef struct

{

    unsigned int X; //占 16 位并按 16 位字对齐;

    unsigned int Y;

    unsigned int Z;

    unsigned int U;

}

datatranstype;

radartype myRadarData[2]={{1, 'a', 'b', 'c', 0, 512}, {2, 'x', 'y', 'z',0,1024 }};

void main(void)

{

    radartype *p;

    datatranstype *q;

    p = myRadarData;

    q = (datatranstype *)p;

    q++;

}

【问题 1】

假如处理机按 16 位以大端方式 (big_endian) 编址,请在下图所示的存储器图表中填入 myRadarData 数据的存储内容 (十六进制表示) 。

解析:

1. 分析结构定义

typedef struct {
    int A : 16;       // 占 16 位(2 字节),按 16 位字对齐
    char B : 8;       // 占 8 位(1 字节)
    char C : 8;       // 占 8 位(1 字节)
    char D : 8;       // 占 8 位(1 字节)
    char E : 8;       // 占 8 位(1 字节)
    int F;            // 占 16 位(2 字节),按 16 位字对齐
} radartype;

注意:题中说“int 占 16 位”,所以 int = 2 字节。
int A : 16 也是 2 字节,按字对齐(即起始地址为偶数)。

结构大小(按成员顺序分配地址,且 16 位对齐,即每个成员地址必须是偶数):

    A:2 字节,起始地址 0x5000(假设)

    B:1 字节,起始地址 0x5002
    (因为在 0x5001 不是 16 位对齐成员,不需要填充,但 char 在 C 中可任意字节对齐;如果按严格字对齐,char 不要求偶数,但这里 0x5002 是偶数,直接放 B)

    C:1 字节,起始地址 0x5003

    D:1 字节,起始地址 0x5004

    E:1 字节,起始地址 0x5005

    F:2 字节,但必须按 16 位字对齐,即起始地址必须是偶数。
    上一个成员 E 地址是 0x5005,下一个可用偶数是 0x5006,所以 F 从 0x5006 开始,占 0x5006–0x5007。

所以 radartype 总大小 = 0x5000–0x5007 共 8 字节。

检查结构体布局(字节地址):
A: 0x5000 0x5001
B: 0x5002
C: 0x5003
D: 0x5004
E: 0x5005
F: 0x5006 0x5007

2. 初始数据

radartype myRadarData[2] = {
    {1, 'a', 'b', 'c', 0, 512},
    {2, 'x', 'y', 'z', 0, 1024}
};

数据值(注意 C 语言大小端影响内存内容):

    int A 是 16 位,值 1 → 0x0001(高 0x00,低 0x01)

    char B = 'a' → ASCII 0x61

    char C = 'b' → 0x62

    char D = 'c' → 0x63

    char E = 0 → 0x00

    int F = 512 → 0x0200(高 0x02,低 0x00)

3. 大端存储(big_endian)

大端模式下,16 位数据的高 8 位放在低地址,低 8 位放在高地址。

myRadarData[0] 字节地址(假设起始地址 0x5000):

myRadarData[1] 紧随其后,起始地址 0x5008(因为 radartype 大小为 8 字节)。

数据 {2, 'x', 'y', 'z', 0, 1024}:

    int A = 2 → 0x0002(高 0x00,低 0x02)

    char B = 'x' → 0x78

    char C = 'y' → 0x79

    char D = 'z' → 0x7A

    char E = 0 → 0x00

    int F = 1024 → 0x0400(高 0x04,低 0x00)

大端存储:

题目给的图是(每行是 16 位字,并排高 8 位+低 8 位):

    0x5000 一行 = 0x5000 (高) + 0x5001 (低)

    0x5002 一行 = 0x5002 + 0x5003

    0x5004 一行 = 0x5004 + 0x5005

    0x5006 一行 = 0x5006 + 0x5007
    这是 myRadarData[0] 的 4 个字(共 8 字节)

    0x5008 一行 = 0x5008 + 0x5009

    0x500A 一行 = 0x500A + 0x500B

    0x500C 一行 = 0x500C + 0x500D

    0x500E 一行 = 0x500E + 0x500F
    这是 myRadarData[1] 的 4 个字(共 8 字节):

【问题2】

在图 所示的程序中,第 22 行的语句执行完毕后,下列语句的结果是多少?请将应填入 (n) 处的内容写在答题纸的对应栏中。

q−>X=(1)​

q−>Y=(2)​

q−>Z=(3)​

q−>U=(4)

若再执行一次 q++,则下列语句的结果又是多少?请将应填入 (n) 处的内容写在答题纸的对应栏中。

q−>X=(5)​

q−>Y=(6)​

q−>Z=(7)​

q−>U=(8)

解析:

radartype 大小已知为 8 字节,结构体成员在内存中的位置(按大端 16 位机,地址以字节为单位):

myRadarData[0](起始地址 0x5000):

myRadarData[1](起始地址 0x5008):

第一次 q++ 之前


p = myRadarData;                 // p 指向 0x5000
q = (datatranstype *)p;          // q 也指向 0x5000,但按 datatranstype 解释
q++;                             // q 增加 1 个 datatranstype(8 字节)

所以执行后 q 指向 0x5008(即 myRadarData[1] 的起始地址)。

第一次 q++ 后的 datatranstype 视图

datatranstype 结构:

  • X: 0x5008–0x5009

  • Y: 0x500A–0x500B

  • Z: 0x500C–0x500D

  • U: 0x500E–0x500F

在大端模式下,从连续字节构造 16 位无符号整数:

(1) X:
0x5008 = 0x00, 0x5009 = 0x02 → 大端值 = 0x0002 = 2

(2) Y:
0x500A = 0x78, 0x500B = 0x79 → 大端值 = 0x7879

(3) Z:
0x500C = 0x7A, 0x500D = 0x00 → 大端值 = 0x7A00

(4) U:
0x500E = 0x04, 0x500F = 0x00 → 大端值 = 0x0400 = 1024

再执行一次 q++

q 当前指向 0x5008,再加一个 datatranstype(8 字节):
q 指向 0x5010(即 myRadarData[2] 的起始地址,如果存在)。

但在原题中,myRadarData 只有 2 个元素,所以 0x5010 是数组外的地址,指向未定义数据。
不过题目可能是想我们忽略越界,认为下一个 radartype 按同样模式存放,即 myRadarData[2] 的 A=3, B='p', C='q', D='r', E=0, F=2048 这样连续的假想数据。

最终答案

第一次 q++ 后:
(1) 2
(2) 0x7879
(3) 0x7A00
(4) 1024

第二次 q++ 后:
(5) 3
(6) 0x7071
(7) 0x7200
(8) 2048

【问题 3】

内存空间常划分代码段(text)、数据段(data)、bss 段(bss)、堆区(heap)和栈区(stack),那么图 中 myRadarData 数组的存储空间应分配在哪段中?指针变量 p、q 应分配在哪段中?

解析:

C 程序的内存布局(典型嵌入式/裸机环境)

通常:

    代码段(text):存放机器指令、常量(如字符串字面量),只读。

    数据段(data):存放已初始化的全局变量、静态变量。

    bss 段:存放未初始化或初始化为 0 的全局变量、静态变量(程序启动时清零)。

    堆(heap):动态分配(malloc / new)。

    栈(stack):局部变量、函数参数、返回地址。

分析 myRadarData

radartype myRadarData[2] = {
    {1, 'a', 'b', 'c', 0, 512},
    {2, 'x', 'y', 'z', 0, 1024}
};

    定义在函数 main 外部(全局作用域)。

    已初始化(有明确的初值)。

    不在任何函数内,不是 static 局部,也不是 auto。

因此 myRadarData 分配在 数据段(data)。

 指针变量 p, q
void main(void)
{
    radartype *p;
    datatranstype *q;
    ...
}

    定义在 main 函数内部,是局部变量。

    没有 static 修饰,所以是自动存储期(auto)。

    存储在栈上。

p, q 分配在 栈区(stack)。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐