1. 项目概述与核心价值
在嵌入式系统开发,尤其是工业控制、通信基站或某些专用设备领域,我们常常会遇到一个经典且棘手的问题:如何让一颗现代的、功能强大的处理器,去“理解”并驱动那些基于老一代总线标准设计的芯片或模块?我最近就接手了这样一个项目,核心任务是将一颗主频颇高的MPC860 PowerQUICC处理器,与一个遵循经典MC68000总线协议的外设进行对接。这听起来有点像让一个精通5G通信的工程师去操作一台老式的电报机,两者协议不同、时序不同、握手方式也不同。但正是这种“跨界”连接,往往能最大化利用现有成熟的硬件模块,降低系统整体成本和开发风险。
MPC860作为一款高度集成的通信处理器,其强大之处在于内置了极其灵活的内存控制器和用户可编程状态机(UPM)。我们的核心思路,就是把这台“现代计算机”的UPM,编程成一台能够精确模仿MC68000总线时序的“信号发生器”。整个设计的精髓不在于增加多少外部逻辑芯片,而在于如何通过软件配置,让MPC860的引脚输出一套完全符合MC68000总线规范的波形。本文将彻底拆解这个过程,从总线协议的本质差异分析开始,到MPC860内部寄存器的逐比特配置,再到UPM编程的具体步骤和波形调试技巧。无论你是正在面临类似兼容性挑战的工程师,还是对处理器总线接口深度编程感兴趣的学习者,这篇从实际项目中沉淀下来的笔记,都能为你提供一条清晰的实现路径和一堆避坑指南。
2. 核心思路:协议翻译与信号映射
要让MPC860与MC68000外设对话,首先得理解这两位“参与者”的语言差异。MC68000总线是一种异步总线,其读写操作依赖于一系列握手信号,如地址选通(AS*)、数据选通(UDS*/LDS*)和传输应答(DTACK*)。处理器发出地址和AS信号,告知外设“我要访问这个位置”,然后通过UDS/LDS指示操作的是高字节、低字节还是字,最后等待外设拉低DTACK表示“数据准备好了”或“数据已接收”。整个过程没有统一的时钟同步,完全靠这些信号线的跳变来推进。
而MPC860的内存控制器,其默认模式是针对同步的SRAM、DRAM或突发传输优化的。它的关键信号是片选(CS*)、字节使能(BS*)和读写(R/W)。直接连接,时序对不上,协议也对不上。因此,我们的设计核心是信号映射和时序重塑。
1. 关键信号映射关系:
- CS-> AS:** 这是最直接的一对一映射。MPC860的片选信号在访问特定内存bank时有效,其作用与MC68000的地址选通信号完全一致,用于锁存地址和标识传输开始。
- BS[1:0]-> UDS/LDS*:** MPC860的字节使能信号BS0和BS1,分别对应数据总线的高字节(D8-D15)和低字节(D0-D7)使能。这正好对应MC68000的高位数据选通(UDS*)和低位数据选通(LDS*)。通过配置,我们可以让BS信号模仿UDS/LDS*的时序行为。
- R/W -> R/W:读写方向信号两者兼容,可以直接连接。
- 地址/数据总线:这部分是直接连通的。需要注意的是,MC68000是16位数据总线,MPC860是32位。在我们的场景中,外设是16位端口且定义在数据总线的高16位(D16-D31),因此我们需要正确配置MPC860的端口大小和对齐方式。
2. 核心挑战与解决方案:
- 时序生成:MC68000的AS*、UDS*/LDS有严格的建立、保持和失效时间要求。MPC860的UPM(用户可编程状态机)正是为此而生。我们可以将UPM编程为一个微码控制器,在内存访问周期的每一个时钟周期,精确控制每一个输出引脚(CS, BS*, GPL等)的电平状态,从而“画”出我们需要的任何波形。
- 功能码(FC0-FC2)生成:MC68000有3根功能码线,用于指示当前访问类型(如用户程序、用户数据、超级用户程序等)。MPC860没有直接对应的引脚。这里有两种方案:一是利用UPM的通用输出线(GPL)在访问周期内输出固定的电平组合来模拟;二是通过外部简单的锁存器或逻辑门,利用MPC860的地址类型(AT0-AT2)信号来生成。本文会详细探讨UPM软件实现的方案。
- 异步应答(DTACK)处理:* MC68000外设通过拉低DTACK来结束总线周期。MPC860需要一种机制来等待这个信号。我们通过将DTACK信号与CS*信号经过一个外部“或非门”(实际常用一个与门加反相器实现)逻辑组合,产生一个UPWAIT信号反馈给MPC860。只要UPWAIT有效,UPM就会暂停其状态转移,冻结所有输出信号,完美实现了对异步应答的等待。
核心心得:在设计之初,一定要拿到双方处理器和外设的数据手册,仔细对比时序图。重点不是记住所有参数,而是理解每个信号在总线周期中的“角色”和先后顺序。把MPC860的UPM想象成一个可编程的逻辑阵列(PLA),我们的任务就是为它编写一段“状态机代码”,让它输出的信号序列能扮演好MC68000的角色。
3. 硬件接口设计与关键电路
在软件编程之前,一个正确可靠的硬件连接是基础。下图是基于文档描述的接口框图,我在此基础上补充了一些在实际布线中需要注意的细节。
MPC860 PowerQUICC ┌─────────────────────────┐ │ │ Address[0:31]│A[0:31] D[16:31]│Data[16:31] (High Word) │ │ │ Memory Controller│ │ & UPM │ │ │ CSx* (Bank) │CS* BS[0]* │→ UDS* (Upper Data Strobe) │ │ │ BS[1]* │→ LDS* (Lower Data Strobe) │ │ │ R/W │→ R/W │ │ GPL_A[0:2] (or)│GPL[0:2] AT[0:2]│──┐ │ (Configurable Outputs) │ │ │ │ │ UPWAITA* │UPWAIT* ←──────┐ │ │ └─────────────────────────┘ │ │ 外部逻辑(可选) │ ┌─────────────┐ └─┤ 逻辑门 ├─→ FC[0:2] DTACK* ←───┤(用于生成FC)│ └─────────────┘ │ ∨ ┌──────────────────┐ │ MC68000 系列 │ │ 外设器件 │ │ │ │ AS* UDS* LDS* │ │ R/W DTACK* │ │ D[0:15] │ └──────────────────┘1. 信号连接详解:
- 数据总线:明确将MC68000外设的16位数据线(D0-D15)连接到MPC860数据总线的高16位(D16-D31)。这是因为我们在配置内存bank时,将其端口大小设为16位,并可能指定了特定的字节对齐方式(通常与
PS字段和地址线连接有关)。确保物理连接与此逻辑配置一致。 - 控制信号直连:
CS*、BS0*、BS1*、R/W直接飞线到对应外设引脚。建议在靠近MPC860端串联一个22Ω或33Ω的电阻,用于阻抗匹配和减少信号过冲,尤其在长走线或较高频率下。 - UPWAIT信号生成电路:这是实现异步等待的关键。文档中提到的“外部OR gate”描述略有歧义,实际上需要一个“与门”逻辑:
UPWAIT = NOT (CS* AND DTACK*)。也就是说,当片选CS*有效(低电平)且外设尚未应答DTACK*为高电平时,UPWAIT应为低有效(告知MPC860等待)。可以使用一个74系列的逻辑与门(如74HC08)和一个反相器(如74HC04)实现,或者直接使用一个与非门(如74HC00)并适当调整逻辑。务必在UPWAIT输入脚加上拉电阻,确保空闲时为无效状态。
2. 功能码生成方案选择:
- 方案A:UPM通用引脚(GPL)输出。这是最灵活的纯软件方案。我们将UPM的通用输出线(例如GPL_A0, GPL_A1, GPL_A2)配置为在对应内存bank的访问周期内,输出预设的电平。例如,访问用户数据区时,让(GPL2, GPL1, GPL0)输出
(0,1,1)。这需要在UPM数组中为每个状态设置GPL的输出值。优点是无需额外芯片;缺点是占用了宝贵的GPL引脚,且这些引脚可能被其他功能(如GPIO)复用,需仔细规划。 - 方案B:外部逻辑译码。利用MPC860在访问外部内存时输出的地址类型信号AT[0:2]。AT信号本身就指示了访问类型(如用户数据、用户程序等)。通过一个简单的3位锁存器(如74HC373)或组合逻辑电路,在
CS*有效时锁存AT[0:2]的值,并输出为FC[0:2]。此方案不消耗UPM资源,且更贴近硬件本质。电路示意:CS*作为锁存使能(LE),AT[0:2]作为输入,锁存器输出即为FC[0:2]。
硬件调试要点:在第一次上电前,务必用万用表检查所有电源和地线是否短路。焊接完成后,先不插处理器,测量各信号线对地电阻,排除焊接短路。首次调试时,建议先不连接MC68000外设,而是用逻辑分析仪或示波器抓取MPC860在访问配置好的内存区域时,
CS*、BS*等信号的波形,确认UPM编程产生的时序基本正确后,再接入外设进行联合调试。这能有效隔离问题。
4. MPC860内存控制器寄存器配置详解
硬件连好了,接下来就是让MPC860的“大脑”——内存控制器,知道如何与这个特殊的“内存区域”打交道。这需要通过配置一对寄存器来实现:基址寄存器(BRx)和选项寄存器(ORx)。我们假设使用Bank 0(即BR0/OR0)来映射这个MC68000外设。
1. 基址寄存器(BR0)配置:基址寄存器定义了内存块的起始地址和基本属性。我们需要关注其中几个关键字段:
- BA (Base Address, Bits 0-16):设置这个外设在MPC860内存映射中的起始地址。例如,设置为
0xF0000000。 - PS (Port Size, Bits 20-21):必须设置为
10,表示这是一个16位端口。这决定了控制器一次传输的数据宽度,并影响BS*信号的行为。 - PARE (Parity Enable, Bit 22):设置为
0,禁用奇偶校验。我们的外设通常不支持。 - MS (Machine Select, Bits 24-25):必须设置为
10或11,分别表示选择UPM A或UPM B来产生这个bank的时序。我们选择UPM A,所以设为10。 - V (Valid Bit, Bit 31):必须设置为
1,该bank配置才生效。在初始化序列中,通常最后设置此位。
2. 选项寄存器(OR0)配置:选项寄存器定义了内存块的掩码和更多时序相关的选项。
- AM (Address Mask, Bits 0-16):设置地址掩码,决定这个bank的地址空间大小。例如,如果外设只有64KB空间(
0x0000FFFF),且起始于0xF0000000,那么AM可以设置为0xFFFF0000,这样访问0xF0000000到0xF000FFFF的地址都会命中此bank。 - SAM (Start Address Multiplex, Bit 20):对于MC68000这类非复用总线,必须设置为
0。这意味着在访问周期开始时,地址线直接输出要访问的地址,而不是行/列复用地址。 - BI (Burst Inhibit, Bit 23):必须设置为
1。这表示该内存块不支持突发传输。MPC860在访问此区域时,会驱动BI信号有效(如果引脚被配置为BI功能),同时UPM也会按非突发模式生成时序。
3. UPM模式寄存器(MxMR)配置要点:这里以UPM A的模式寄存器(MAMR)为例:
- PTAE (Periodic Timer A Enable, Bit 8):根据需求设置。如果不使用UPM的周期性定时器功能,可以设为
0(禁用)。 - GPL_A4DIS (GPL_A4 Output Disable, Bit 19):这个位控制着
UPWAITA*/GPL_A4*引脚的功能。在我们的设计中,该引脚被用作UPWAIT输入,因此此位必须设置为1。设置为1后,该引脚的功能由UPM数组中的G4T4/DLT3和G4T3/WAEN位决定,我们将在UPM数组中将其配置为等待输入功能(WAEN)。
4. 初始化代码示例(C语言片段):
/* 定义寄存器地址 (示例,具体地址请参考MPC860手册) */ #define IMMR_BASE 0xF0000000 #define MEMC_BASE (IMMR_BASE + 0x0000) #define BR0 (*(volatile unsigned long *)(MEMC_BASE + 0x500)) #define OR0 (*(volatile unsigned long *)(MEMC_BASE + 0x504)) #define MAMR (*(volatile unsigned long *)(MEMC_BASE + 0x1A8)) /* 假设外设映射到 0xF0000000 - 0xF000FFFF,64KB空间 */ #define MC68K_BASE_ADDR 0xF0000000 #define MC68K_MASK 0xFFFF0000 // 掩码后高16位需匹配BASE_ADDR的高16位 void mc68k_bus_init(void) { /* 1. 暂时禁用Bank 0 */ BR0 &= ~0x00000001; // 清除V位 /* 2. 配置选项寄存器 OR0 */ OR0 = 0; OR0 |= (MC68K_MASK & 0xFFFF0000); // 设置地址掩码AM[0:16] OR0 |= (0 << 20); // SAM = 0, 非复用地址 OR0 |= (1 << 23); // BI = 1, 禁止突发 /* 3. 配置基址寄存器 BR0 */ BR0 = 0; BR0 |= (MC68K_BASE_ADDR & 0xFFFF0000); // 设置基址BA[0:16] BR0 |= (0x2 << 20); // PS = 10, 16位端口 BR0 |= (0x0 << 22); // PARE = 0, 禁用奇偶校验 BR0 |= (0x2 << 24); // MS = 10, 使用UPM A BR0 |= (0x1 << 31); // V = 1, 使能此Bank /* 4. 配置UPM A模式寄存器 MAMR (部分位) */ MAMR &= ~((1 << 8) | (1 << 19)); // 根据需要配置,例如禁用周期性定时器 MAMR |= (1 << 19); // GPL_A4DIS = 1, UPWAITA引脚用作等待输入 /* 5. 接下来,需要配置UPM RAM数组,这是时序生成的核心 */ /* upm_config() 函数将在下一节实现 */ }寄存器配置陷阱:配置
BRx和ORx时,最常见的错误是AM掩码计算错误,导致地址映射范围不对。另一个易错点是PS和MS字段设置不匹配。PS定义了数据宽度,MS选择了时序发生器,两者必须协同工作。务必在设置V位前,确保其他所有参数都已正确写入,因为一旦V位置1,对该bank区域的访问立即生效,如果时序(UPM)还未配置,可能会导致总线错误或锁死。
5. UPM RAM编程:打造MC68000时序发生器
这是整个项目的核心与灵魂。UPM RAM是一个64x32位的存储器阵列,每个字(32位)对应一个状态(State),每个状态持续一个时钟周期。UPM像一个小型状态机,根据当前状态和输入(如UPWAIT),在下一个时钟周期跳转到由当前UPM RAM字中指定的下一个状态,并按照当前字的定义输出各信号的电平。
1. UPM RAM字结构解析:一个32位的UPM RAM字(我们称之为“微指令”)控制着一个时钟周期内总线的行为。关键字段包括:
Rn(Run, Bits 0-3):在当前状态保持的时钟周期数减一。0000表示保持1个周期,1111表示保持16个周期。用于延长特定状态的持续时间,以满足外设的时序要求(如地址建立时间tAS)。OPx(Operation, Bits 4-7):操作码。0000表示等待UPWAIT变无效后继续;0100表示跳转到指定状态并等待UPWAIT;1100表示跳转到指定状态(不等待)。我们主要用0100(带等待跳转)和1100(无条件跳转)。MDx(Machine Dependent, Bits 8-15):机器依赖字段。对于内存控制器,它定义了CS*、BS*、GPL等输出信号在当前周期的值。我们需要根据MC68000的时序图,为每个状态精心设置这些比特。ADx(Address, Bits 16-31):跳转地址。当OPx指示跳转时,这个字段指定下一个状态在UPM RAM中的行号(0-63)。
2. 设计一个MC68000读周期UPM序列:我们以最简单的读周期为例。假设MPC860的时钟是50MHz(周期20ns),MC68000外设要求AS*有效后,地址建立时间tAS至少为50ns,数据访问时间tACC最大为200ns。
我们需要将整个读周期分解成多个状态(假设从状态0开始):
- 状态0 (S0):初始状态。输出:
CS*(即AS*)无效(高),BS*无效(高),GPL输出功能码(例如111表示用户数据)。Rn=0000(1周期),OPx=1100(无条件跳转),ADx=1(跳转到状态1)。 - 状态1 (S1):地址建立期。输出:
CS*变低(有效),地址线已稳定,BS*仍为高(数据选通稍后)。Rn=0010(3个周期,共60ns > 50ns,满足tAS)。OPx=1100,ADx=2。 - 状态2 (S2):数据选通有效。输出:
CS*保持低,根据是字/字节访问,拉低相应的BS*(UDS*/LDS*)。Rn=0000(1周期)。OPx=0100(带等待跳转),ADx=3。关键点:此时UPWAIT信号因CS*有效且DTACK*未有效而为低,UPM会暂停在此状态,直到UPWAIT变高(即外设拉低DTACK*应答)。 - 状态3 (S3):数据采样与周期结束。
UPWAIT变高后,UPM才进入此状态。输出:CS*变高,BS*变高。Rn=0000(1周期)。OPx=1100,ADx=0(跳回初始状态,准备下一次访问)。
3. UPM RAM数组填充示例(简化示意):我们需要将上述状态描述翻译成具体的32位数值,并写入UPM RAM。UPM RAM通常通过内存控制器的特定寄存器(如MPTP、MDR)进行编程。下面是一个概念性的数组,每个元素对应一个状态(行)的微指令值。
/* UPM A RAM 数组,每个元素是一个32位微指令 */ /* 此数组需根据具体时序参数计算得出,以下为示意值 */ unsigned long upm_a_ram_read[] = { /* 状态0: 空闲,输出FC=111 (用户数据),CS高,BS高 */ 0x0FF0F000, // Rn=0, OP=1100, MD=... (CS高, BS高, GPL=111), AD=0 (实际跳转到1,此处AD应为1,示意) /* 状态1: 地址建立,CS低,BS高,保持3周期 */ 0x1FF0F001, // Rn=2 (3周期), OP=1100, MD=... (CS低, BS高), AD=2 /* 状态2: 数据选通,CS低,BS低,等待UPWAIT */ 0x0CF0F002, // Rn=0, OP=0100 (等待跳转), MD=... (CS低, BS低), AD=3 /* 状态3: 恢复,CS高,BS高,返回空闲 */ 0x0FF0F000, // Rn=0, OP=1100, MD=... (CS高, BS高), AD=0 /* ... 其他状态,例如写周期序列 */ }; void upm_config(void) { int i; /* 假设存在设置UPM RAM地址指针和写入数据的寄存器 */ volatile unsigned long *upm_addr_reg = ...; volatile unsigned long *upm_data_reg = ...; *upm_addr_reg = 0; // 从UPM RAM第0行开始写入 for (i = 0; i < sizeof(upm_a_ram_read)/sizeof(unsigned long); i++) { *upm_data_reg = upm_a_ram_read[i]; /* 可能需要触发一个写操作或地址自增 */ } /* 可能还需要设置MAMR中的UPM启动地址等 */ }UPM编程核心技巧:计算
Rn字段是满足时序要求的关键。总保持时间 = (Rn+ 1) * 系统时钟周期。务必留出足够余量。最易出错的地方在状态2的OPx设置:必须使用0100(等待跳转),而不是1100(无条件跳转)。只有0100才会让UPM在UPWAIT有效时“原地踏步”,实现异步等待。调试时,可以先用1100代替0100,观察不等待时的基本波形是否正确,然后再加入等待逻辑。
6. 软件访问与功能码控制
硬件和UPM都配置好后,从软件角度看,访问这个MC68000外设就变得像访问普通内存一样简单。但由于我们可能模拟了多种功能码,需要一种机制来控制每次访问时输出的功能码。
1. 内存区域划分与功能码关联:一种简洁的设计是为不同的功能码分配不同的内存地址区间,尽管它们可能指向同一个物理外设。通过配置多个BRx/ORx对(但指向相同的物理地址范围),并为每个bank编写不同的UPM序列,可以实现这一点。但这样会浪费UPM RAM空间和bank资源。
更常用的方法是利用UPM的通用输出线(GPL)。我们可以在UPM序列中,让GPL引脚在访问周期内输出固定的电平。通过编写不同的UPM序列(例如读用户数据、写用户程序等),每个序列中设置不同的GPL输出值。软件通过调用不同的函数或访问不同的“虚拟地址”来触发不同的UPM序列。
2. 软件接口函数示例:
/* 定义访问宏或函数,底层指向同一个物理地址,但可能触发不同的UPM序列 */ #define MC68K_BASE_PHYS 0xF0000000 /* 假设我们通过修改UPM起始状态来切换序列 */ /* 序列0: 读用户数据 (FC=111) */ /* 序列1: 写用户数据 (FC=111) */ /* 序列2: 读用户程序 (FC=101) */ /* 序列3: 写用户程序 (FC=101) */ static inline unsigned short mc68k_read_user_data(unsigned long offset) { /* 设置UPM从“读用户数据序列”开始 (例如状态0) */ set_upm_start_state(0); return *((volatile unsigned short *)(MC68K_BASE_PHYS + offset)); } static inline void mc68k_write_user_data(unsigned long offset, unsigned short data) { set_upm_start_state(1); *((volatile unsigned short *)(MC68K_BASE_PHYS + offset)) = data; } static inline unsigned short mc68k_read_user_program(unsigned long offset) { set_upm_start_state(2); return *((volatile unsigned short *)(MC68K_BASE_PHYS + offset)); } /* set_upm_start_state() 函数需要通过设置某个寄存器来实现, 例如MCR(内存命令寄存器)的某个字段,或者通过向一个特定的 “命令触发地址”进行写操作来切换UPM的起始状态。具体方法需查阅 MPC860手册中关于UPM运行控制的部分。 */3. 另一种思路:单一序列与动态GPL控制如果UPM资源紧张,也可以只编写一个通用的读写序列。在访问外设之前,先通过GPIO控制器手动设置与GPL复用的那几个引脚的电平(输出所需功能码),然后再进行内存访问。访问结束后再恢复引脚状态。这种方法增加了软件开销,但节省了UPM RAM。
软件层注意事项:确保编译器不会对指向该内存区域的操作进行优化(如合并写操作、预读等),使用
volatile关键字至关重要。另外,由于是异步总线,访问速度较慢,在频繁操作时需要考虑加入必要的延迟或使用查询/中断机制,避免处理器性能被过度拖慢。在驱动层,最好将这部分访问封装成独立的函数,并做好互斥保护,防止多任务访问造成时序混乱。
7. 调试技巧与常见问题排查
将这套系统调通,逻辑分析仪是你的最佳伙伴。以下是一些实战中总结的调试步骤和常见问题:
1. 调试步骤:
- 静态检查:确认所有寄存器配置值已正确写入。可以通过调试器读取
BR0、OR0、MAMR等寄存器进行验证。 - UPM信号基础测试:暂时将
UPWAIT信号通过电阻上拉至高电平(使其无效)。编写一个简单的测试程序,循环读取MC68000映射地址。用逻辑分析仪同时抓取CS*、BS*、R/W、地址线、数据线。观察CS*和BS*的波形是否基本符合MC68000的时序形状(先有CS*,后有BS*)。此时因为UPWAIT无效,UPM不会等待,周期会很快结束。 - 加入等待测试:恢复
UPWAIT电路。在DTACK*信号线上人为加一个下拉脉冲(可以用一个GPIO模拟),模拟外设应答。观察UPWAIT信号是否随之变低,并且CS*和BS*的负脉冲宽度是否被拉长,直到DTACK*有效后才结束。 - 功能码验证:触发不同的访问函数,测量GPL引脚或外部逻辑生成的
FC[0:2]信号,看其电平是否与预期功能码一致。 - 实际外设联调:连接真实MC68000外设。先进行读ID或状态寄存器等简单操作。如果失败,检查数据线连接、电源、以及外设本身的片选和使能信号。
2. 常见问题与解决方案:
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
| 访问时处理器进入总线错误或检查点 | 1. 访问了未配置V=1的地址。2. UPM序列错误,导致总线周期无法正常结束(超时)。 3. UPWAIT信号电路故障,始终为低。 | 1. 检查BRx的V位和地址映射。2. 用逻辑分析仪抓取 CS*和UPWAIT,看周期是否异常漫长。检查UPM序列中等待状态(OPx=0100)的设置和跳转逻辑。3. 测量 UPWAIT引脚电平,检查外部逻辑电路。 |
CS*或BS*信号无输出 | 1. 对应的内存bank未使能(V=0)。2. UPM未运行或起始状态错误。 3. 引脚复用功能未配置为内存控制器功能。 | 1. 确认BRx的V=1,且访问地址落在其范围内。2. 检查UPM模式寄存器配置,确认UPM已启用且起始地址正确。 3. 检查MPC860的引脚控制寄存器(PxPAR),确保 CS*、BS*等引脚被设置为内存控制器功能,而非GPIO。 |
| 波形时序不符合MC68000要求 | 1. UPM序列中各个状态的保持时间(Rn字段)计算错误。2. 系统时钟频率设置与计算时假设不符。 | 1. 仔细计算外设的tAS、tDS等参数,根据系统时钟周期调整UPM RAM中相关状态的Rn值。必要时增加等待状态。2. 确认MPC860的核心时钟和总线时钟频率配置是否正确。 |
| 功能码输出不正确 | 1. GPL引脚输出值在UPM RAM中设置错误。 2. 外部逻辑电路连接或逻辑错误。 3. 引脚复用配置错误。 | 1. 核对UPM RAM中MDx字段对应GPL输出的比特位。2. 用逻辑分析仪测量GPL或 AT[0:2]引脚,对比预期值。检查外部逻辑芯片的电源、连接和真值表。3. 确认GPL引脚已通过 MAMR等寄存器正确配置为UPM输出功能。 |
| 读写数据错误 | 1. 数据线连接错误(高位/低位接反)。 2. 字节使能 BS*信号与外设的UDS*/LDS*对应关系错误。3. 外设本身需要特殊的初始化或访问序列。 | 1. 检查PCB布线,确认D0-D15与MPC860的D16-D31一一对应。 2. 确认是 BS0*接UDS*还是BS1*接UDS*,这与“高字节”的定义有关。尝试交换。3. 查阅MC68000外设的数据手册,确认其是否有上电复位序列、寄存器访问顺序等要求。 |
3. 逻辑分析仪设置要点:
- 采样率:至少为系统时钟频率的5倍以上,最好能达到10倍,以清晰捕捉信号边沿。
- 触发条件:设置为
CS*的下降沿触发,这样可以稳定捕获整个访问周期。 - 分组显示:将地址线、数据线、控制线(
CS*,BS*,R/W,UPWAIT,DTACK*,FC)分别分组,并设置为总线显示模式(二进制或十六进制),便于观察。 - 时序测量:利用分析仪的测量工具,直接测量
CS*有效到BS*有效的延迟(tAS)、BS*有效到DTACK*有效的延迟(访问时间)、以及CS*的总脉宽。
调试此类接口,耐心和细致的信号观察至关重要。从一个最简单的读操作开始,确保每一个信号都如预期般动作,然后再逐步增加写操作、不同的功能码等复杂度。成功的关键在于对MPC860 UPM工作机制的深刻理解和对MC68000总线协议的准确把握。当看到逻辑分析仪上呈现出完美的、由你编程产生的MC68000时序波形时,那种成就感正是嵌入式硬件编程的魅力所在。