ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DSP外部接口XINTF详解:时序配置与调试实战指南

DSP外部接口XINTF详解:时序配置与调试实战指南 搞DSP开发尤其是用TI C2000系列的朋友对XINTF这个外设应该不陌生。我当年复习到外部接口模块时绕了不少弯路后来把手册里相关章节反复啃了几遍又在实际板子上调过SRAM和Flash的读写时序才算真正把这部分吃透。这篇笔记就按我自己的复习思路来整理重点讲清楚XINTF是什么、怎么配置、时序怎么算、以及实际调试中那些手册里不会明说的坑。如果你正在学DSP、准备找工作面试或者刚接手一个需要外扩并行存储器/ADC/DAC的项目这篇内容会比较对口。我会把寄存器配置、时序计算、硬件连接这些关键点串起来讲尽量让零基础的同学也能跟上。1. XINTF是什么为什么需要它XINTF全称是External Interface翻译过来就是外部接口。它是TI C2000系列DSP上的一块并行总线控制器用来扩展处理器地址空间之外的外部器件最常见的场景就是外扩SRAM、NOR Flash以及一些并口ADC/DAC。1.1 核心需求解析为什么要用外部接口原因很直接DSP芯片内置的RAM和Flash容量有限。拿经典的TMS320F28335来说片内SRAM大概34KBFlash 512KB。跑一个稍微复杂的算法比如电机控制里的FFT加观测器数据缓存很容易就把片内RAM挤爆。这时候你想在外部挂一块256KB的SRAM或者挂一块1MB的Flash存固件和查表数据就得靠XINTF把地址总线和数据总线引出去。还有一个场景是接高速并口外设。有些高精度ADC比如逐次逼近型或者Delta-Sigma型输出是16位并行数据用GPIO模拟时序去读不仅占用大量引脚时序稳定性也差。通过XINTF把ADC映射到DSP的某个地址区域一条读指令就能把数据取回来硬件自动完成时序控制既快又省心。1.2 XINTF在C2000系列中的定位XINTF在C2000不同型号上设计有差异。早期的F2812有19位地址线、16位数据线支持Zone0到Zone7共6个区域Zone1和Zone2合用一个片选Zone6和Zone7合用一个片选到了F28335地址线扩展到20位数据线支持16位或32位模式区域划分也调整成Zone0、Zone6、Zone7三个独立区域加一个Zone1/2共用区域。其他系列比如F2806x、F2803x大多没有XINTF只有高端型号才带这个外设。这块在设计时是有意为之的工业控制类的2803x/2806x追求低成本和低功耗不需要大容量外部存储而2833x/2834x面向高性能伺服、并网逆变、电力电子仿真存储扩展能力和总线吞吐就是刚需。理解了这个产品定位你就明白为什么选型时不能只看主频还得看有没有XINTF、地址位宽是多少、能不能支持32位数据总线。2. 整体框架与设计思路拆解2.1 区域划分与片选逻辑XINTF把整个外部地址空间划分成若干Zone每个Zone有独立的片选信号和独立的时序配置寄存器。F28335为例外部接口区域如下Zone片选信号地址范围典型用途Zone0XZCS00x000800-0x000FFFSRAM、网络芯片Zone1/2XZCS1/20x080000-0x0FFFFFFlash、FPGAZone6XZCS60x100000-0x17FFFFSRAM、ADCZone7XZCS70x200000-0x21FFFFBoot Flash、大容量存储每个Zone的片选独立拉低意味着你可以给不同的外设分配不同的访问时序。比如Zone6挂的SRAM读写只要15ns就可以稳定Zone7挂的Flash需要70ns的读周期那你分别配置两个Zone的建立时间、激活时间、恢复时间互不干扰。这个设计非常实用如果所有外部器件共用一套时序参数你就只能迁就最慢的那个整体性能白白被拖累。2.2 地址总线、数据总线与读写控制信号XINTF对外引出的信号包括地址总线XA[19:0]、数据总线XD[31:0]F28335支持32位模式F2812只有16位、片选XZCSn、读写控制XRD和XWE、以及XREADY和XHOLD等握手信号。这里有个容易混淆的点XINTF的地址线是按字寻址还是按字节寻址。C2000的CPU最小寻址单位是16位字所以XINTF的地址总线也是按字对齐的。如果访问32位数据实际地址在内部左移一位后输出到XA上具体移位规则查对应型号的Technical Reference手册。我当年调试时就在这栽过跟头用32位模式访问数组打印地址总是偶数的后来才明白硬件自动做了字到字节的转换。数据线宽度方面XINTF可以配置为16位或32位。数据线宽度不等于总线位宽这个很关键。如果外接的存储器是16位的你可以把XINTF配成16位模式高16位数据线XD[31:16]不使用如果你配成32位模式但外设是16位那么连续两个字会被拼成一个32位访问低16位对应存储器的第一个字高16位对应第二个字这种模式对SRAM和Flash做连续存储非常高效。2.3 访问仲裁与等待状态XINTF支持XHOLD和XHOLDA仲裁信号允许外部设备请求总线。这个功能在DMA和外部主机共享SRAM时很常用。XHOLD拉低时XINTF会在当前访问结束后释放总线拉低XHOLDA作为应答外部设备获得总线控制权访问完成后释放XHOLDXINTF重新接管。这个机制实现简单但要注意如果软件里长期占用总线XHOLD请求一直得不到响应外部设备的看门狗可能就触发了。XREADY信号则负责插入等待状态。当你外接的器件速度比较慢XINTF按配置的时间参数完成一次访问后器件数据还没准备好这时器件可以拉低XREADYXINTF就会自动插入等待周期直到XREADY变高才完成本次访问。注意XREADY的使用要配合XINTFCNF寄存器里的XREADY极性位来配置而且只在建立阶段采样XREADY具体采样窗口由XTIMING寄存器的USEREADY位决定。3. 寄存器配置与要点详解3.1 XINTFCNF配置寄存器解析XINTFCNF是XINTF的全局配置寄存器主要配置位有XTIMCLK分频XTIMCLK可以等于系统时钟SYSCLKOUT也可以二分频或四分频。所有Zone的时序参数都是以XTIMCLK为基准计数的所以这个分频值决定了外部接口的最小时钟粒度。XHOLD/XHOLDA使能控制外部总线仲裁功能是否启用。XREADY极性选择选择XREADY是高有效还是低有效。XMPNMC模式选择有些型号根据这个位决定是否启用XINTF功能置1启用。数据总线宽度16位还是32位。WRITE_BUFFERING和READ_MODE写缓冲使能和读模式选择。读模式有正常读和流水线读两种流水线读对SRAM这种地址建立后延时输出数据的器件效果更友好。配置XINTFCNF时我建议第一步就把时钟分频确定下来尽量不要在运行时反复改动。因为所有时序参数都是基于XTIMCLK的你在计算建立/激活/恢复周期之前必须先锁定XTIMCLK频率否则前面算好的参数全部作废。3.2 XINTFXTIMING时序寄存器分组每个Zone有一组XTIMING寄存器控制读和写的时序参数。XINTFXTIMING寄存器主要有这几组位域XWRTRAIL写恢复时间XWRACTIVE写激活时间XWRLEAD写建立时间XRDLEAD读建立时间XRDACTIVE读激活时间XRDTRAIL读恢复时间USEREADY是否使用XREADYXSIZE位宽选择某些型号放这里这些时间单位不是纳秒而是XTIMCLK的周期数。比如你配置XRDLEAD 3意味着读片选信号拉低前地址总线先稳定3个XTIMCLK周期。手册里把这些参数称为LEAD、ACTIVE、TRAIL三段合起来就是一次完整总线访问的三个阶段。3.3 配置流程实例演示我拿F28335配一个挂载在Zone6的16位SRAM举例假设SYSCLKOUT 150MHzXTIMCLK选二分之一分频即75MHz一个周期约13.33ns。SRAM芯片的时序参数地址建立时间最小8ns读脉冲宽度最小12ns片选到数据有效最大15ns写脉冲宽度最小10ns地址保持时间最小5ns。按这些参数反推XTIMCLK周期数建立时间8ns / 13.33ns 0.6向上取整取1保守一点取2激活时间12ns / 13.33ns 0.9取1保守取2恢复时间5ns / 13.33ns 0.375取1所以配置XRDLEAD 1XRDACTIVE 2XRDTRAIL 1写侧同理XWRLEAD 1XWRACTIVE 2XWRTRAIL 1。USEREADY 0不启用XREADY。这里有一个经验值所有时间参数我习惯在计算理论值的基础上加1到2个周期做裕量。因为PCB走线延迟、信号完整性导致的边沿变缓、温度漂移都会让实际时序变差不留裕量的话板子可能在实验室正常到现场环境一热就偶发读写错误。代价是单次访问多几个时钟周期但换来的是可靠性划算。4. 实操过程与核心环节实现4.1 硬件连接与信号完整性XINTF的硬件连接有几个注意点。第一地址线和数据线不要交叉错位。XINTF的地指标XA[19:0]对应存储器的地址引脚时要严格按照同编号连接地址总线错位是硬件调试中最容易出问题的地方之一。数据线同理XD[15:0]对应外部器件的DQ[15:0]。第二片选信号必须去耦。XZCSn在每次访问时都会拉低再拉高是板上一根高频翻转的信号线建议串联一个33欧姆到50欧姆的电阻可以明显减少振铃。我在示波器上实测过不加串阻时片选信号过冲接近1V加33欧姆后基本平了。第三如果外部器件比较多数据总线的驱动能力会变差。这时需要在数据线上加总线缓冲器比如74LVC16245。这个缓冲器的方向控制引脚DIR和输出使能OE要接对DIR接XRD信号OE接地线或者接到XZCSn反相后的信号。接反了就会出现写正常读乱码或者反过来。4.2 用一段代码跑通SRAM读写我习惯用一个简单的读写测试来验证XINTF配置是否正确。方法是往一片SRAM的首地址写一组递增数然后读回来比对。#define ZONE6_BASE 0x100000 #define TEST_LEN 1024 void Xintf_SramTest(void) { Uint16 i; Uint16 errCnt 0; Uint16 *sramPtr (Uint16 *)ZONE6_BASE; // 初始化XINTF使用Zone6 InitXintf(); // 写入递增数据 for (i 0; i TEST_LEN; i) { sramPtr[i] i; } // 回读比对 for (i 0; i TEST_LEN; i) { if (sramPtr[i] ! i) { errCnt; } } if (errCnt 0) { // 测试通过 } else { // 打印错误次数 } }写测试时要注意C2000的编译器对volatile的处理。上面代码中sramPtr指向的是外部地址建议声明为volatile指针否则编译器可能优化掉回读操作。我在不开优化时测试一切正常一开-O2就发现回读数据全对不上后来加了volatile就好了。4.3 用TI提供的库函数初始化和手动寄存器初始化TI的controlSUITE和C2000Ware里提供了XintfInit()这类现成函数里面是一堆寄存器宏定义直接调用就行。但我不建议你直接跑库函数不改动因为你用的外设时序参数跟TI例程里的扩展SRAM不一定一致。最好打开库函数源码一行行对照你手里的SRAM数据手册把时序参数改过来。手动初始化的话配置步骤归纳如下设置XINTFCNF的XTIMCLK分频和位宽根据需要使能XHOLD、设置XREADY极性配置对应Zone的XTIMING寄存器读时序和写时序分别设置若有多个Zone逐一配置用一段已知数据做读写自检实际操作中我碰到一种情况想用Zone6挂SRAMZone7挂Flash两个Zone的时序不同但XINTFCNF是全局的位宽只能设置一次。如果SRAM是16位Flash也是16位那没问题但如果Flash想用32位模式加速启动而SRAM只有16位那是做不到的因为XINTF的数据位宽是全局配置不能按Zone单独设置。选型时就要提前考虑好这个问题。5. 常见问题与排查技巧实录5.1 读写数据总是错的几个典型原因XINTF调试中数据错误是最让人头疼的。按我经验按以下顺序排查能覆盖大部分问题地址线错位用示波器看XA0到XA19的波形确认第一位地址是否按预期翻转。地址线错位会导致访问地址变成原来的两倍或一半。例如你写地址0x100000实际访问的是0x200000读回来的数据自然是乱的。数据总线驱动冲突如果外部器件是三态输出片选信号没有正确控制OE引脚两个器件就会同时驱动数据总线出现数据竞争。排查方法是分别只使能一个器件看读取是否正常。时序裕量不足用示波器看片选和读信号的时序宽度对照数据手册的最小值。如果ACTIVE周期算少了数据还没稳定就被采样就会出现随机性数据错误。表现是写死数据后回读绝大多数地址对个别地址错而且出错位置不固定。5.2 写Flash时擦除失败怎么办挂NOR Flash时擦除和编程需要满足Flash特定的时序要求。如果擦除命令发出去后Flash状态寄存器一直返回忙有个常见原因是XINTF写时序中的激活时间不够导致命令字没被正确锁存。解决办法是适当加大XWRACTIVE比如从2改到4或6。另外要注意的是NOR Flash的编程命令序列要求连续的写操作中间不能插入其他总线访问。如果XINTF写缓冲使能了会出现写命令被缓冲后后续读状态命令提前到达Flash命令序列被打断。遇到这种问题可以在发编程命令前禁用写缓冲或者每次写完命令后加一个小的延时。5.3 在在线调试时正常脱机运行却出错这个问题在XINTF和外部Flash配合启动时经常出现。在线仿真时调试器会通过JTAG初始化DSP并配置好XINTF然后引导代码访问外部Flash没问题。脱机运行时DSP上电后boot ROM先运行再跳转到外部Flash执行而此时XINTF寄存器里面还是上电默认值时序参数完全不对读出来的指令就是乱码。解决思路是在上电初始化代码里尽早配置XINTF越早越好。如果是从外部Flash启动那启动引导代码本身就要放在一个能正确访问Flash的环境里——这变成一个鸡生蛋的问题。常见做法是先用内部Flash放一段极简的初始化代码配置好XINTF后再跳转到外部Flash的正式程序。也有些项目用CPLD/FPGA在硬件上完成xintf的默认时序映射让DSP上电后不需要配置就能读取外部Flash的初始指令但这种方式复杂度高一般项目不需要。5.4 问题排查速查表现象可能原因排查手段读出全为0片选没生效或OE信号错误量XZCSn和XRD波形读出全为0xFF数据总线悬空器件未驱动查器件供电和复位量片选地址每两位跳变地址线错位或字/字节模式混淆查XA连接和位宽配置偶发读写错误时序余量不足或上拉弱增大时序参数检查上下拉写入后回读不一致写信号宽度不够或写缓冲问题加大XWRACTIVE关闭写缓冲程序跑飞外部Flash启动时序未初始化内部代码先配XINTF再跳转6. 经验补充从EMIF移植和跨平台使用的思考XINTF和TI另一大系列C6000/AM335x上的EMIFExternal Memory Interface功能相似但寄存器体系和时序定义有差异。如果你以前只调过EMIF转过来用XINTF时别直接套老经验。EMIF的时序寄存器通常直接以纳秒或时钟周期配置而XINTF的LEAD/ACTIVE/TRAIL设计更接近经典CPU总线的三段式时序模型。理解了这个模型再去看任何并口存储器时序图都会轻松很多。网上有人问“DSP EMIF位宽怎么接Flash”其实思路上和XINTF接Flash是一样的。位宽匹配的核心原则是DSP数据总线宽度和存储器位宽相等时一一对应直接连接DSP数据总线比存储器宽时要么把DSP配置成窄位宽模式要么通过多片存储器并联扩展成宽位宽。反向情况存储器位宽比DSP总线宽那就需要额外逻辑做总线宽度转换XINTF本身不支持这种模式。还有一个容易被忽视的点是XINTF引脚复用。C2000很多引脚是复用的XINTF信号默认不一定使能。你需要通过GPIO MUX寄存器把对应的引脚切换成XINTF功能。F28335上XINTF引脚和普通GPIO复用如果忘了配置GPIO复用XINTF的地址线根本不输出外部器件永远片选不了。这个坑我在第一次画板子时碰到过硬件连了半天才发现是软件没开复用功能。关于GPIO复用配置建议在初始化XINTF之前先把所有相关引脚的MUX都设好形成一个专门的InitXintfGpio()函数。以后换板子或者换芯片型号时只需要改这个函数里的引脚配置不用动时序部分维护起来方便很多。7. 实操过程记录一次完整的外部SRAM调试前面讲了理论和配置这里记录一次完整的调试过程方便你对比自己的操作流程。7.1 硬件环境与初始配置板子用F28335外扩一片64KB的16位SRAM挂在Zone6片选接XZCS6地址线XA[15:0]接SRAM的A[15:0]数据线XD[15:0]接SRAM的D[15:0]。SRAM的OE接XRDWE接XWECE接XZCS6。SYSCLKOUT设置为150MHzXTIMCLK二分频为75MHz。7.2 寄存器配置具体数值按前面计算XTIMING寄存器设置如下以Zone6为例XRDLEAD 1建立1个周期即13.33nsXRDACTIVE 2激活2个周期即26.67nsXRDTRAIL 1恢复1个周期XWRLEAD 1XWRACTIVE 2XWRTRAIL 1USEREADY 0XSIZE 16位配置完以后先用简单的单地址读写验证再跑数组遍历测试。7.3 调试中遇到的真实问题第一次跑测试时回读数据错误率约5%出错地址完全随机。用示波器观察XZCS6和XRD时序发现片选低电平期间有严重的振铃幅度接近逻辑阈值导致数据采样不稳定。排查发现SRAM的片选引脚和DSP引脚之间走线过长且没有端接电阻板子设计初期没考虑信号完整性。解决方法是把XINTF所有控制信号尤其片选、读、写串联33欧姆电阻降低振铃幅度。改完以后连续跑100万次读写测试错误为0。这个经验后来在所有带XINTF的板子上我都直接预留着串阻位置根据实际波形选择焊还是不焊。7.4 关于BIT_BANDING和超长突发传输的思考有些项目需要连续搬运大量数据比如采集卡把ADC数据存到外部SRAM。XINTF的连续访问效率取决于burst能力。F28335的XINTF在连续访问时能自动切换地址但每次切换地址都会重新经历LEAD阶段。所以理想情况是把数据按块复制而不是随机单点访问这样地址递增时地址线已经稳定LEAD时间可以压缩到最短。结合DMA使用XINTF是另一个提升效率的方向。DMA控制器可以直接把外部SRAM的数据搬到内部RAM或者反向搬运全程不占CPU。这个组合在数据采集系统里非常常用。不过DMA触发源和XINTF地址范围的配合需要仔细查表DMA的源地址和目标地址要支持XINTF区域映射不是所有型号都支持选型时要注意。8. 针对不同应用场景的配置建议8.1 数据采集系统外挂ADC通过XINTF接入时读时序要重点关注XRDALEAD。ADC通常在片选拉低后的若干个时钟周期内输出数据如果XRDACTIVE太短DSP可能在ADC还没有驱动数据总线时就采样了。遇到这种情况优先增加XRDACTIVE而不是XRDLEAD因为ADC的转换启动往往由前一次读操作触发本次读到的数据对应前一次转换结果需要理解这个流水关系。也就是说你在读第N个数据时ADC正在转换第N1个下一次读才能拿到第N1个结果。所以软件上要连续读两次第一次丢弃取第二次的数据。这个特性在逐次逼近型ADC里很常见并不是XINTF的问题。8.2 外部Flash存储Code和数据的存放方式会影响XINTF的配置侧重。如果是纯数据存储比如记录运行日志写时序重要性高于读时序写恢复时间要给足防止连续写操作时数据丢失。如果是从外部Flash跑代码读时序的确定性就更关键ACTIVE和TRAIL都要保证足够代码在Flash中执行时任何一次读取超时都可能触发CPU异常。有一种做法是把Flash中执行的代码段拷贝到内部RAM里运行这样外部Flash只需要在启动阶段被正确读取一次之后XINTF时序压力小很多也更稳定。很多bootloader项目就是这么设计的。8.3 扩展并行设备组合板子上同时挂SRAM、Flash和FPGA时三个器件的时序和位宽可能各不相同。这种情况下我的建议是按访问频率排序最频繁访问的器件用独立的Zone并且时序最优访问频率低的器件可以共用Zone区域但要注意地址空间重叠问题。可以巧妙地利用地址译码逻辑在同一个Zone片选下面用高位地址区分不同器件这个办法可以省片选但需要额外的外部逻辑电路。对大多数项目而言独立片选更清晰调试也方便不建议为了省几个引脚引入额外复杂度。9. 基于个人经验的最终建议最后分享几个我实际做项目中总结出来的经验不一定都在手册里写得很明白。第一XINTF引脚的GPIO复用配置别忘。好多朋友在软件初始化时把所有外设都配置好了就是忘了把引脚切换成XINTF功能结果外部器件毫无响应。把这个函数放在InitXintf()之前作为板级初始化的一部分固定下来。第二时序参数要留足裕量但不是越大越好。设置过大的LEAD和ACTIVE会显著降低访问效率。如果程序的性能瓶颈在外部存储访问上你就得在可靠性跟速度之间做平衡。我的经验是最低裕量取一个XTIMCLK周期温度变化和板间差异基本都能覆盖。第三XINTF调试时建议配备示波器或者逻辑分析仪至少也要有万用表。软件上无论怎么调都解决不了硬件连接问题波形测量是最直接的排查手段。尤其是地址线是否错位、片选是否有毛刺、数据总线是否有竞争这些用示波器一目了然。回顾整个XINTF的学习过程我觉得最有价值的部分不是寄存器背得多熟而是真正理解了总线访问三段式时序模型、位宽匹配原则和硬件信号完整性对软件的影响。掌握了这些底层逻辑再去看不同型号DSP的XINTF差异、甚至移植到别的带并行总线的处理器上都会轻松很多。希望这份复习笔记能帮正在学DSP的同学少走些弯路。
返回列表