1. 项目概述:深入MC9328MXL的MSHC寄存器世界
搞嵌入式底层驱动,尤其是存储接口这块,寄存器手册就是我们的“武功秘籍”。最近在折腾一个基于Freescale MC9328MXL的老项目,需要对接Memory Stick存储卡。翻出那本厚厚的参考手册,第19章讲Memory Stick主机控制器(MSHC)的部分,密密麻麻的寄存器位定义和协议时序图,初看确实让人头大。但真正啃下来才发现,这套由索尼主导的存储协议,其设计思想相当精巧,而MC9328MXL的MSHC模块则提供了一个高度集成的硬件解决方案。寄存器编程,说白了就是通过读写芯片上特定地址的内存单元,来直接指挥硬件干活。比如,你想让MSHC开始一次数据读取,不是调某个高级API,而是往Memory Stick Command Register里写一个特定的命令码(PID);你想知道数据是否准备好,不是去轮询某个标志,而是检查Memory Stick Interrupt Control/Status Register里的DRQ(Data Transfer Request)位。这种“直接对话”的方式,剥夺了操作系统抽象层的“翻译”过程,带来的好处是极致的效率和可控性,尤其适合对实时性和功耗有严苛要求的嵌入式场景。当然,代价就是开发者得直面硬件的复杂性,对时序、状态机、中断同步要有清晰的认识。本文,我就结合手册和实际调试经验,把MC9328MXL MSHC的核心寄存器掰开揉碎了讲清楚,再串起Memory Stick的通信协议,希望能帮你少走点弯路。
2. MSHC核心寄存器详解与配置逻辑
MC9328MXL的MSHC模块提供了一组寄存器,用于控制整个Memory Stick的通信流程。理解每个寄存器的位功能,是编写稳定驱动的前提。手册里列出了不少寄存器,我们挑最核心、最常用的几个来重点剖析。
2.1 中断控制与状态寄存器(MSICS)
这个寄存器是驱动程序的“眼睛”和“耳朵”,几乎所有关键事件都会在这里留下状态标志。其地址是0x0021A006(根据手册上下文推断,需结合芯片内存映射表确认)。
核心位域解析:
- SIF (Bit 6) - 串行接口中断:当Memory Stick通过SDIO线发出中断信号(INT)时,此位被硬件置1。这个中断独立于数据就绪(RDY)信号。关键点在于清除方式:手册明确写着“Cleared by writing to the Memory Stick Command Register”。这意味着,你需要通过下发一个新的命令(哪怕是无实际操作的命令)来清除这个中断标志,而不是直接写0。同时,当
INTEN位为1时,读取本寄存器(MSICS)会清除内部的中断请求(MSIRQ)。 - DRQ (Bit 5) - 数据传输请求:这是DMA或CPU轮询模式下的核心标志。当FIFO满足特定条件(例如接收FIFO有数据可读,或发送FIFO有空位可写)时,此位置1。它的行为与
DRQSL位紧密相关:只有当MSICS寄存器中的DRQSL位为1时,DRQ位才能被硬件改变。清除方式也分情况:如果是写命令(主机发送数据),则向FIFO写入数据后会清除它;如果是读命令(主机接收数据),则从FIFO读取数据后会清除它。同样,读取MSICS寄存器也能清除其中断请求。注意:
DRQEN位(在MSDRQC寄存器中)是DMA请求的总开关。即使DRQ位为1,如果DRQEN=0,DMA请求信号也不会产生。这在调试DMA传输失败时是首要检查点。 - PIN (Bit 4) - 并行输入变化:用于检测MS_PI[1:0]引脚的电平变化,常用来做卡的热插拔检测。当引脚电平变化时置1。清除方式是读取
MSPPCD(并行端口控制/数据寄存器),这设计意味着你可能需要先处理引脚状态,再读一下MSPPCD(哪怕不关心其数据)来清除此中断。 - FAE (Bit 2) - FIFO访问错误:指示发生了非法的FIFO访问,例如在接收FIFO为空时尝试读取(下溢),或在发送FIFO已满时尝试写入(上溢)。此状态位的使能由
MSFAECS寄存器中的FAEEN位控制。清除方式是读取MSFAECS寄存器。这个寄存器对调试主机或DMA控制器对FIFO的访问序列非常有用。 - CRC (Bit 1) - CRC错误:在数据包传输中校验失败时置位。发生CRC错误时,BS线会被拉低,RDY信号变高并产生中断。清除方式是向Memory Stick命令寄存器写入数据(通常意味着需要重新发起传输或进行错误处理流程)。
- TOE (Bit 0) - 超时错误:当Memory Stick的BSY信号持续时间超过
BSYCNT(在某个控制寄存器中设置)所设定的时钟数时置位。这通常被视为卡端故障。清除方式同样是向Memory Stick命令寄存器写入数据。
配置心得: 在初始化时,通常会先读取一次MSICS以清除任何可能的上电残留状态。在中断服务程序(ISR)中,第一步就是读取MSICS,根据位状态判断中断源,然后执行相应的操作(如填充/清空FIFO),并按照手册规定的特定操作清除中断标志,这是避免中断丢失或重复触发的关键。很多人容易忽略不同中断位需要不同的清除方式,导致程序行为异常。
2.2 并行端口控制/数据寄存器(MSPPCD)
这个寄存器主要用于管理两个通用的并行输入引脚MS_PI[1:0],地址为0x0021A008。
- PIEN1, PIEN0 (Bits 13,12):分别使能MS_PI1和MS_PI0引脚作为并行输入端口。通常用于卡检测(Card Detect)或写保护(Write Protect)信号。需要使能相应位,模块才会去检测该引脚的电平变化并可能触发PIN中断。
- XPIN1, XPIN0 (Bits 5,4):只读位,直接反映MS_PI[1:0]引脚当前的逻辑电平(0=高电平,1=低电平)。手册里有个重要提示:从引脚电平变化到反映到XPIN位,有大约30个HCLK周期的延迟。在编写卡检测逻辑时,必须考虑这个延迟,不能读得太快。
- 内部上拉与工作模式:手册提到MS_PI引脚内部有上拉电阻。此外,引脚状态检测功能在MCU的正常模式(Normal)和打盹模式(Doze)下均可用,只要MSHC模块被使能(
MSCEN=1)。
实操要点: 假设MS_PI0连接卡检测开关(卡插入时接地,拔出时由上拉电阻拉高)。初始化时,设置PIEN0=1,使能该引脚检测。在卡状态查询或中断服务中,读取XPIN0,若为1则表示卡插入(低电平),为0则表示卡拔出(高电平)。注意处理消抖和30个时钟的延迟。
2.3 控制寄存器2(MSC2)与自动命令寄存器(MSACD)
这两个寄存器控制着一些高级和便利功能。
MSC2寄存器(0x0021A00A)关键位:
- ACD (Bit 15) - 自动命令使能:这是一个非常实用的功能。当置1时,MSHC在检测到来自Memory Stick的INT信号后,会自动执行预设的命令。这可以简化主机处理异步中断的流程,将“中断-响应-发命令”简化为“中断-自动响应”。
- RED (Bit 14) - 时钟沿选择:选择串行数据在SCLK的上升沿还是下降沿被锁存。必须与Memory Stick卡端的时序要求严格匹配,通常遵循主设备(主机)输出数据在时钟下降沿变化,从设备(卡)在上升沿采样的原则,但具体需看卡规格。
- LEND (Bit 1) - 字节序:设置FIFO数据的字节序。0为大端(Big Endian),1为小端(Little Endian)。这需要与主机CPU的字节序以及你对数据在内存中的解释方式保持一致,否则读出来的数据高低字节是反的。
- MSCEN (Bit 0) - 模块使能:MSHC模块的总开关。特别注意:手册用Note强调,此位不会被MSCS寄存器中的RST位复位。这意味着如果你用软件复位(RST)了MSHC,
MSCEN依然保持原值,模块可能仍���于使能状态。安全的做法是,在软件复位序列中,先清除MSCEN,再置位RST,等待后再重新配置并置位MSCEN。
MSACD寄存器(0x0021A00C): 当ACD=1时,此寄存器定义自动执行的动作。
- APID (Bits 15:12):设置自动执行的命令PID。手册示例中
0100代表READ_REG(读寄存器),0111代表GET_INT(获取中断状态)。GET_INT是一个常用自动命令,用于在收到卡中断后自动读取卡的中断状态寄存器,主机只需从FIFO读取结果即可。 - ADATASIZE (Bits 9:0):设置自动命令的数据传输大小(字节数)。对于
GET_INT,固定为1字节;对于READ_REG,则需根据要读取的寄存器数量来设置。
2.4 FIFO访问错误控制/状态寄存器(MSFAECS)
这个寄存器是调试FIFO相关问题的利器,地址为0x0021A00E。
- FAEEN (Bit 8):FIFO访问错误检测的总使能。必须置1,
RUN和TOV状态位以及MSICS中的FAE中断位才会生效。 - RUN (Bit 1):接收FIFO下溢访问标志。当接收FIFO为空(
RBE=1)时,主机或DMA还试图读取,此位置1。清除方式很特别:写1清零。 - TOV (Bit 0):发送FIFO上溢访问标志。当发送FIFO已满(
TBF=1)时,主机或DMA还试图写入,此位置1。清除方式同样是写1清零。
调试经验: 在DMA传输不稳定或数据丢失时,除了检查DMA控制器配置,一定要查看这个寄存器。如果RUN或TOV被置位,说明主机/DMA的访问节奏与MSHC内部FIFO的生产-消费速度不匹配。可能的原因包括:DMA请求阈值(RFF/TFE)设置不当、中断响应太慢、或者软件读写FIFO的时机不对。这个寄存器能帮你快速定位问题是出在主机侧还是MSHC模块侧。
2.5 DMA请求控制寄存器(MSDRQC)
这是协调MSHC与DMA控制器协同工作的桥梁,地址为0x0021A012。
- DRQEN (Bit 15):DMA请求使能。务必在启动DMA传输前将其置1,否则DMA请求信号永远不会发出。
- RFF (Bit 4):控制读命令(如
READ_REG,READ_PAGE_DATA)时的DMA请求条件。0:当Rx FIFO收到至少半个字(16位)数据时产生DMA请求。适用于每次DMA传输搬运少量数据(如1个半字)。1:当Rx FIFO满(4个半字,即8字节)时才产生DMA请求。适用于希望减少DMA传输次数,每次搬运更多数据的场景。- 重要关联:此位的有效性取决于MSCS寄存器中的
DAKEN位。当DAKEN=0时,MSHC只在RFF=0的条件下产生DMA请求。因此,如果你想使用RFF=1(FIFO满请求)的模式,必须同时将DAKEN置1。
- TFE (Bit 0):控制写命令时的DMA请求条件。
0:当Tx FIFO至少有1个空位(可容纳1个半字)时产生DMA请求。1:当Tx FIFO完全空时才产生DMA请求。- 同样,其有效性也受
DAKEN位控制。
配置策略: 对于大数据量连续传输(如读写页数据),通常设置RFF=1且TFE=1,并置位DAKEN。这样可以让DMA以最大块(8字节)为单位搬运数据,最大化总线效率,减少中断或DMA请求次数。对于小数据量或寄存器访问,可能使用RFF=0/TFE=0甚至轮询模式更合适。手册还特别说明,当使用DMA时,DMA控制器的突发长度(Burst Length)必须设置为2字节或8字节,以匹配MSHC FIFO的深度和DMA请求条件。
2.6 串行时钟分频寄存器(MSCLKD)
此寄存器(0x0021A010)用于生成Memory Stick通信所需的串行时钟SCLK。
- SRC (Bit 15):选择分频器的源时钟。0表示选择内部HCLK。手册警告,在正常操作期间此位不能设置为1。
- DIV (Bits 1:0):分频比选择。
00=1分频,01=2分频,10=4分频,11=8分频。关键限制:- 当
SRC=0(HCLK)时,DIV设置不能为00(即不支持1分频)。 - 此位必须在
MSCEN=0(模块禁用)时才能修改。一旦使能了MSHC模块,再修改DIV是无效或危险的。 - 此位不受MSCS寄存器中RST位的影响。这意味着分频设置是“持久”的,软件复位不会改变它。
- 当
时钟计算示例: 假设HCLK为60MHz,设置DIV=11(8分频),则产生的SCLK基础频率为 60MHz / 8 = 7.5MHz。Memory Stick协议通常支持多种时钟速率,需确保此频率在卡支持的范围内。
3. Memory Stick通信协议深度解析
寄存器是控制手段,协议则是通信的语言。MSHC与Memory Stick之间通过三条线通信:MS_BS(总线状态)、MS_SDIO(串行数据)和MS_SCLK(串行时钟)。理解其协议状态机是编写正确驱动的基础。
3.1 四状态访问模式(Four State Access Mode)
这是正常数据传输时的标准模式,一次完整的包(Packet)通信包含四个状态(BS0-BS3),由MS_BS信号的电平指示。
各状态详解:
BS0 (MS_BS = LOW) - 中断传输状态:
- 功能:无包通信活动。此时MS_SDIO线被用作中断(INT)信号线。Memory Stick通过将SDIO拉高来向主机发送中断信号,表示有事件需要处理(如写操作完成、发生错误等)。
- 关键特性:INT信号是异步的,不与SCLK同步。主机通过检测SDIO线的高电平来感知中断,并通过查询MSICS寄存器的SIF位来确认。
BS1 (MS_BS = HIGH) - TPC状态:
- 功能:包通信开始。主机通过MSHC向Memory Stick发送传输协议命令(TPC)。TPC是一个8位编码,高4位是命令,低4位是其反码,用于错误检测。
- 方向:主机(MSHC) → Memory Stick。
BS2 和 BS3:这两个状态的功能取决于当前是读包还是写包。
- 对于写包(Write Packet):
- BS2 (LOW) - 数据传输状态:主机通过MSHC向Memory Stick发送数据及CRC校验码。
- BS3 (HIGH) - 握手状态:Memory Stick接收数据后,进行内部处理。在此期间,它先在SDIO上输出BSY信号(固定高或低电平),表示“忙”;处理完成后,输出RDY信号(在每个SCLK周期翻转的电平),表示“就绪”,准备结束本次包传输。
- 对于读包(Read Packet):
- BS2 (LOW) - 握手状态:Memory Stick在SDIO上输出BSY信号,表示正在准备数据;数据准备好后,输出RDY信号。
- BS3 (HIGH) - 数据传输状态:Memory Stick通过SDIO向主机发送数据及CRC校验码。
- 对于写包(Write Packet):
协议流程图(以写包为例):
主机发起写操作: BS0 (常态) --(主机启动传输)--> BS1 (发送TPC命令) --> BS2 (发送数据+CRC) --> BS3 (等待卡响应) ^ | | v `--(卡输出RDY,包结束) <-- (卡处理完成,输出RDY) <-- (卡接收数据,输出BSY)整个流程由MSHC硬件自动管理,驱动程序主要负责设置好TPC命令、数据地址和长度,然后启动传输,并等待中断(DRQ用于数据搬运,SIF/CRC/TOE用于包完成或错误)。
3.2 传输协议命令(TPC)详解
TPC是主机控制Memory Stick的指令集,通过8位编码传达。手册中定义了几种核心TPC:
| TPC名称 | TPC[3:0] | 操作 | 描述 |
|---|---|---|---|
READ_PAGE_DATA | 0010 | 从��缓冲读取 | 从Memory Stick的页缓冲区读取固定512字节数据+CRC。用于块数据读取。 |
READ_REG | 0100 | 读寄存器 | 读取Memory Stick内部寄存器。需先用SET_R/W_REG_ADRS命令设置地址和长度。 |
GET_INT | 0111 | 读中断寄存器 | 专用于快速读取Memory Stick的1字节中断状态寄存器,无需预先设置地址。 |
WRITE_PAGE_DATA | 1101 | 写页缓冲 | 向页缓冲区写入固定512字节数据+CRC。用于块数据写入。 |
WRITE_REG | 1011 | 写寄存器 | 向Memory Stick内部寄存器写入。需先用SET_R/W_REG_ADRS命令设置地址和长度。 |
SET_R/W_REG_ADRS | 1000 | 设置寄存器地址 | 为后续的READ_REG或WRITE_REG设置起始地址和连续访问的寄存器数量。数据段固定为4字节。 |
SET_CMD | 1110 | 设置CMD | 向闪存控制器发送命令(如擦除、编程等)。数据段为8位命令码+CRC。 |
TPC使用流程示例(读取某个寄存器):
- 主机发送
SET_R/W_REG_ADRSTPC,数据段包含:寄存器起始地址(2字节)、要读取的寄存器数量(2字节)。 - 主机发送
READ_REGTPC。 - MSHC自动进入读包流程,在BS3状态从Memory Stick接收指定长度的寄存器数据+CRC。
- 主机从MSHC的接收FIFO中读取数据。
GET_INT的特殊性:因为它如此常用(用于轮询或中断后查询卡状态),所以被设计为独立的TPC,无需前置的SET_R/W_REG_ADRS,简化了操作。
3.3 二状态访问模式与错误处理
当通信过程中发生错误时,为防止总线冲突,Memory Stick会自动退回到一种简化的二状态访问模式(Two State Access Mode)。在此模式下,只有BS0和BS1两个状态。
触发二状态模式的错误因素:
- TPC代码错误:接收到的TPC高4位与低4位反码校验失败,或收到未定义的TPC代码。
- 不可接受的TPC:Memory Stick因内部状态(如忙)无法执行收到的TPC。
- TPC状态过短:BS1状态的持续时间少于8个SCLK周期。
- 数据错误:写包时CRC校验失败,或数据状态(BS2/BS3)持续时间短于预期。
- 握手错误:在Memory Stick正常输出RDY之前,BS状态就被切换。
- 电源上电。
主机侧的表现与处理: 当Memory Stick因错误进入二状态模式时,主机侧在握手状态(对于写包是BS3,对于读包是BS2)会等待RDY信号,但永远等不到,从而导致超时错误。MSHC的MSICS寄存器中的TOE位会被置位。
驱动程序的错误恢复流程:
- 检测到
TOE或CRC错误标志。 - 向Memory Stick命令寄存器写入数据(任何值,通常可重发原命令或发一个
GET_INT)以清除错误状态位。 - 发送
GET_INT命令查询Memory Stick的状态,确认错误原因。 - 根据错误类型进行恢复,如重试操作、重置MSHC模块(设置RST位)、甚至重新初始化卡。
- 协议规定,在二状态模式下,主机只能发送TPC(BS1状态)。通过发送
GET_INT等TPC,并收到正确响应后,总线有可能自动恢复回四状态模式。
3.4 信号时序与扩展机制
手册中关于时序的细节是保证通信物理层稳定的关键。
- 基本时序:发送方在SCLK的下降沿更新SDIO数据,接收方在SCLK的上升沿锁存数据。BS信号的变化与最后一个数据位(LSB)的输出同步。
- 总线状态扩展(Bus State Extension):在TPC状态或数据状态,如果主机难以在传输完最后一位数据的同时切换BS信号,可以保持当前BS状态不变,延长该状态。在数据状态扩展期间,SDIO线必须保持高电平。
- 数据等待与SCLK扩展(SCLK Extension for Data Wait):这是流控机制。如果主机(发送方)来不及提供下一个数据,或者Memory Stick(接收方)来不及接收,可以通过保持SCLK为高电平来暂停时钟,从而延迟下一个数据的传输。这为处理速度不匹配提供了弹性。
调试建议: 在初始调试阶段,建议用逻辑分析仪或示波器抓取MS_BS、MS_SDIO、MS_SCLK三根线的波形。对照手册的时序图,可以清晰看到BS状态的切换、TPC和数据位的传输、以及RDY/BSY信号的变化。这是排查物理层问题(如时钟频率过快、时序不满足建立保持时间)最直接的方法。
4. 驱动开发实践与问题排查
理解了寄存器和协议,最终要落到代码上。下面分享一些在MC9328MXL上开发MSHC驱动的核心步骤和常见坑点。
4.1 MSHC驱动初始化流程
- 引脚复用配置:将对应的GPIO引脚功能切换到MSHC(MS_BS, MS_SDIO, MS_SCLKO, MS_PI[1:0], MS_SCLKI)。通常需要配置GIUS(GPIO In Use)和GPR(General Purpose Register)寄存器。
- 时钟配置:根据系统HCLK频率和Memory Stick卡支持的时钟范围,配置
MSCLKD寄存器的DIV位。务必在MSCEN=0时配置。 - 基本控制寄存器配置:
- 配置
MSC2:设置字节序LEND、时钟沿RED,根据需要决定是否使能自动命令ACD。 - 配置
MSPPCD:使能需要用到的并行输入引脚PIENx。 - 配置
MSDRQC:如果使用DMA,设置DRQEN=1,并根据传输策略配置RFF和TFE,注意DAKEN位的关联设置。 - 配置
MSFAECS:如果需要FIFO错误调试,使能FAEEN。
- 配置
- 使能模块:将
MSC2寄存器的MSCEN位置1。 - 软件复位(可选但推荐):向
MSCS寄存器的RST位写1,然后等待一小段时间(参考手册或实测),再写0清除。注意:此操作不会清除MSCEN,但会复位大部分其他状态。 - 中断配置:配置MCU的中断控制器,将MSHC的中断线(MSIRQ)映射到对应的CPU中断向量,并编写中断服务程序(ISR)。在ISR中,首先读取
MSICS寄存器判断中断源。 - 卡检测:读取
MSPPCD的XPINx位,或使能PIN中断,来检测Memory Stick是否插入。
4.2 典型数据传输流程(以DMA读取页数据为例)
- 设置DMA:配置DMA控制器的源地址(MSHC数据寄存器)、目标地址(内存缓冲区)、传输长度(如512字节)、传输宽度(半字或字,需与MSHC FIFO及
RFF设置匹配)、并启用DMA通道。 - 配置MSHC DMA:确保
MSDRQC中DRQEN=1,RFF设置与DMA突发长度匹配(例如,RFF=1对应DMA请求在FIFO满时触发,适合8字节突发)。 - 发送读命令:
- 如果需要,先发送
SET_R/W_REG_ADRS设置地址(对于读页,通常不需要,页读地址由其他机制指定)。 - 向Memory Stick命令寄存器写入
READ_PAGE_DATA的TPC代码。
- 如果需要,先发送
- 启动传输:MSHC硬件自动开始与Memory Stick的协议交互(四状态访问)。
- DMA搬运:当Rx FIFO数据达到
RFF设定的阈值时,MSHC向DMA控制器发出请求,DMA自动将数据从MSHC FIFO搬移到内存缓冲区。 - 传输完成:当512字节数据全部传输完毕,MSHC会结束包通信,可能产生传输完成中断或置位相应状态位。驱动程序检查状态,确认无CRC或超时错误。
4.3 常见问题与排查技巧
问题:数据传输完全不动,无任何DRQ或中断。
- 检查1:
MSCEN位是否已置1?模块是否已使能? - 检查2:
MSICS寄存器中的DRQSL位是否为1?它控制DRQ位能否被置起。 - 检查3:
MSDRQC寄存器中的DRQEN位是否为1?(如果使用DMA或DRQ中断)。 - 检查4:TPC命令是否正确发送?检查写入命令寄存器的值是否正确,并确认在发送命令前,MSHC是否处于就绪状态(例如,检查
MSCS中的忙标志位,如果存在)。 - 检查5:用逻辑分析仪看MS_BS、SDIO、SCLK是否有波形?如果没有,检查引脚复用配置和时钟分频设置。
- 检查1:
问题:DMA只能搬运一次数据,后续数据不动。
- 检查1:DMA传输模式是否正确配置为“自动重载”或“循环模式”?对于连续数据流,需要配置DMA在完成一次传输后,自动重置计数器和地址(如果是双缓冲则切换缓冲区)。
- 检查2:MSHC的DMA请��条件(
RFF/TFE)与DMA控制器的突发长度、传输宽度是否匹配?例如,RFF=1(FIFO满请求)意味着需要至少8字节数据才触发请求,那么DMA的传输宽度应设为半字(16位)或字(32位),且最小传输量应设为4个半字或2个字。 - 检查3:在DMA传输完成中断中,是否正确地重新配置或启动了DMA通道以进行下一轮传输?
问题:频繁出现CRC错误或超时错误(TOE)。
- 检查1:SCLK时钟频率是否过高?超过Memory Stick卡所能支持的最高频率。尝试降低
MSCLKD的分频比。 - 检查2:电源是否稳定?Memory Stick在电压不稳时容易通信失败。
- 检查3:PCB布线是否有问题?SDIO和SCLK线是否过长,有无串扰?确保信号完整性。
- 检查4:时序参数是否满足?检查MC9328MXL的MSHC时序特性与Memory Stick卡时序要求的匹配情况,特别是建立时间和保持时间。
- 检查5:是否在错误未清除时尝试发起新传输?发生CRC或TOE错误后,必须先向Memory Stick命令寄存器写入数据(清除错误),并可能需要进行错误恢复流程,才能开始新的传输。
- 检查1:SCLK时钟频率是否过高?超过Memory Stick卡所能支持的最高频率。尝试降低
问题:FIFO访问错误(FAE)被置位。
- 检查:读取
MSFAECS寄存器,看是RUN(下溢)还是TOV(上溢)被置位。RUN=1:说明在Rx FIFO为空时,主机或DMA还试图读取。检查数据读取逻辑,确保只在DRQ置位或FIFO非空时才读。TOV=1:说明在Tx FIFO已满时,主机或DMA还试图写入。检查数据写入逻辑,确保只在DRQ置位或FIFO非满时才写。
- 这通常是软件流控与硬件FIFO速度不匹配的标志,需要优化数据搬运的时机或使用DMA。
- 检查:读取
问题:无法检测到卡插入/拔出。
- 检查1:
MSPPCD寄存器中的PIENx位是否已使能对应引脚? - 检查2:读取
XPINx位时,是否考虑了约30个HCLK周期的延迟?插入卡后应等待一段时间再读取状态。 - 检查3:硬件连接是否正确?MS_PI引脚是否通过合适的上拉/下拉电阻连接到了卡座的检测开关?
- 检查4:是否使能了
PIN中断,并在中断服务程序中正确清除了中断标志(通过读MSPPCD)?
- 检查1:
调试工具箱:
- 寄存器打印:在关键操作前后,打印所有MSHC相关寄存器的值,这是最基础的调试手段。
- 逻辑分析仪:连接MS_BS, MS_SDIO, MS_SCLK三根线,可视化整个协议交互过程,无可替代。
- 示波器:检查电源纹波和信号质量。
- 软件模拟:在初期,可以尝试用GPIO模拟MSHC的时序来与Memory Stick通信,这能帮助你更深刻地理解协议,但性能很低,仅用于验证。