摘要:本文讨论如何使用安全数字(SD)媒体格式扩展MAXQ2000的非易失数据存储器。
低功耗、低噪声的MAXQ2000微控制器适合于多种应用。MAXQ2000在闪存中存储非易失性数据,并和用户代码空间共享32k字(64kB)的闪存容量。但如果你的应用需要更多的非易失性存储器怎么办呢?这篇文章说明了如何使用安全数码(SD™)存储介质来扩展MAXQ2000的非易失性数据存储器。
其次,在保证能为目标应用提供足够带宽的前提下,应将连接外部存储器的MAXQ2000 I/O数限制到最少。例如,Atmel的AT29LV512闪存芯片与一个主机微控制器连接时,需要15条地址线、8条数据线和3条控制线。由于MAXQ2000没有外部地址/数据总线,在上述例子中,就需要由软件来控制总线事务。对于某些应用来说,这种方法不能很有效地利用MAXQ2000的I/O引脚。
然而,基于SPI™和I²C的外部闪存器件只需要3到4个接口引脚。MAXQ2000具有一个硬件SPI模块,而I²C在MAXQ2000上必须由用户通过软件实现(即"位模拟")。这种集成功能使得SPI接口成为访问外部非易失性存储器的主要途径。
由于SD卡采用专有的共享总线,乍一看,似乎很难与MAXQ2000接口。然而,SD继承了MMC的第二总线格式-SPI。由于MAXQ2000提供SPI硬件支持,连接非常容易。
图1. MAXQ2000与SD存储卡的接口非常简单。
图1的威廉希尔官方网站 图给出了一个典型应用威廉希尔官方网站 。SD卡要求全双工、8位SPI操作。数据从MAXQ2000的MOSI引脚同步输入SD卡的DI引脚,并由SD卡的DO线同步输入MAXQ2000的MISO引脚。数据在CLK信号的上升沿同步输入和输出。在每次数据传输的末尾还必须提供8个额外的时钟,以允许SD完成任何未完结的操作。对应这些额外时钟的输入数据必须全为1。识别阶段的时钟频率必须限定在400kHz以内,但SD卡一经识别后,时钟频率便可提高到25MHz。
CRC算法将被保护的数据用选中的除数进行除法运算,产生一个余数。因为该算法中用得的是多项式,所以该除法运算不含进位逻辑。无需考虑进位时,除法运算可通过逻辑XOR操作来实现。所选中的除数通常用CRC的多项式来表示。接着,计算出的余数和数据一起传输,接收器用此余数来检查确认数据在传输过程中是否正常。
对于CRC-7,余数可通过一个7位移位寄存器在软件中计算。计算开始时,将该移位寄存器初始化置为全零。当受保护数据的每一位(MSB在先)被移入移位寄存器的LSB时,移出移位寄存器的MSB,并进行检查。如果移出的位为1,则用CRC-7多项式系数0x09进行异或运算,以此来修正移位寄存器的内容。如果从移位寄存器中移出的位为0,则无需XOR操作。受保护数据的最后一位被移入移位寄存器且完成了条件XOR操作后,必须按此类似方式移入7个或更多0。这一过程称作扩张并完成多项式除法运算。此时,CRC-7值可从移位寄存器直接读出。
图2. 通过移位寄存器架构计算CRC-7。
当接收器收到所有受保护的数据后,接收器可计算基于受保护数据的CRC-7值并将改值与接收到的CRC-7值进行比较。如果这两个值不同,接收器就能判断出受保护数据在传输过程中出现错误。如果这两个值相同,则接收器可完全判定通信通道上的数据是完整的。
CRC-16算法可用同样的方式来构建。在这种情况下,移位寄存器长度为16位而不是7位;多项式系数改为0x1021,且输入数据通过16个0位来扩张。
图3. 发送给存储卡的SPI模式SD命令采用6字节格式。
表1. 部分SD存储卡命令
图4. R1响应指示发出的命令是否成功执行。
SD卡进入SPI模式后,SD规范要求主机在进行其它任何请求之前先发送一条初始化命令。为了能区分MMC卡和SD卡,SD卡采用了一种不同的初始化命令,MMC卡对该命令是不响应的。先向卡发送命令55 (APP_CMD),紧接着再发送应用命令41 (SEND_OP_COND),这样即完成了这个重要的步骤。MMC卡对命令55不做回应,通过这一点可鉴别出MMC卡,并将其视作无效介质而拒绝访问。这个命令序列要一直重复执行,直到来自存储卡的R1响应中所有位均为0 (也就是说,IDLE位变为低)才停止。
清单1. 代码必须用SEND_OP_COND来识别SD和MMC卡。
SD卡包含了一些重要的寄存器,用来提供SD卡的相关信息。最重要的寄存器是存储卡特定数据寄存器(CSD)。对于我们的应用示例而言,我们感兴趣的是存储器的数据块大小和总容量。我们还必须对存储卡标识数据寄存器(CID)加以注意,因为它包含了存储卡的制造商详细信息和序列号。图5显示了CSD寄存器和CID寄存器的配置结构。
图5. CSD寄存器和CID寄存器提供SD卡的相关信息。
图6. 从SD卡到主机的数据传输要加入一个起始令牌作为前缀。
如果完成了SD介质的读取操作并且没有错误发生,则先发送一个起始数据令牌,接着是固定数量的数据,最后是两个字节的CRC-16校验和。如果SD卡碰到硬件故障或介质读取错误,则不会发送起始数据令牌。而是发送一个错误令牌,数据传输随之中止。
如果数据被接受,SD卡会在存储卡忙时始终将DO线保持为低电平。存储卡忙期间,主机不必始终将卡选择线保持为低电平,如果解除CS选择状态,SD卡将释放DO线。当多于一个的设备与SPI总线连接时,上述处理方式非常有用。主机可以一直等待SD卡释放忙指示标志,也可以定期触发片选信号以检查存储卡的工作状态。如果卡仍然处于忙状态,它会将DO线拉低以指示该状态。否则,存储卡会使DO线返回至空闲状态(见图7)。
图7. 从主机到SD卡的数据传输使用一套更为复杂的握手机制。
清单2. 强烈推荐使能CRC校验和。
低功耗、低噪声的MAXQ2000微控制器适合于多种应用。MAXQ2000在闪存中存储非易失性数据,并和用户代码空间共享32k字(64kB)的闪存容量。但如果你的应用需要更多的非易失性存储器怎么办呢?这篇文章说明了如何使用安全数码(SD™)存储介质来扩展MAXQ2000的非易失性数据存储器。
外部存储器的设计考虑
对于你的应用设计来说,首要应该考虑电源电压和电流的要求。在典型的MAXQ2000应用中,可采用一个双路线性稳压器,从而在所选的时钟频率下使处理器工作于尽可能低的核心电压(VDD)下。MAXQ2000的VDD电压可低至1.8V。VDDIO为MAXQ2000的I/O引脚供电,允许的电压范围最低至VDD,最高可达3.6V。可接受的外部存储器电流消耗受限于电源的额定电流,对于电池供电设备,则电流消耗受限于电池系统的容量。其次,在保证能为目标应用提供足够带宽的前提下,应将连接外部存储器的MAXQ2000 I/O数限制到最少。例如,Atmel的AT29LV512闪存芯片与一个主机微控制器连接时,需要15条地址线、8条数据线和3条控制线。由于MAXQ2000没有外部地址/数据总线,在上述例子中,就需要由软件来控制总线事务。对于某些应用来说,这种方法不能很有效地利用MAXQ2000的I/O引脚。
然而,基于SPI™和I²C的外部闪存器件只需要3到4个接口引脚。MAXQ2000具有一个硬件SPI模块,而I²C在MAXQ2000上必须由用户通过软件实现(即"位模拟")。这种集成功能使得SPI接口成为访问外部非易失性存储器的主要途径。
SD存储卡
SD存储介质是一种非易失性外部存储器,可满足许多应用的上述要求。SD格式是"多媒体卡" (MMC)格式的继任产品。SD卡存储器一般工作于3.3V电压,具有适度的电流要求。SD卡的容量从几兆字节到最高4GB不等。容量范围如此之宽,可为众多应用提供充足的外部存储空间。由于SD卡采用专有的共享总线,乍一看,似乎很难与MAXQ2000接口。然而,SD继承了MMC的第二总线格式-SPI。由于MAXQ2000提供SPI硬件支持,连接非常容易。
图1. MAXQ2000与SD存储卡的接口非常简单。
图1的威廉希尔官方网站 图给出了一个典型应用威廉希尔官方网站 。SD卡要求全双工、8位SPI操作。数据从MAXQ2000的MOSI引脚同步输入SD卡的DI引脚,并由SD卡的DO线同步输入MAXQ2000的MISO引脚。数据在CLK信号的上升沿同步输入和输出。在每次数据传输的末尾还必须提供8个额外的时钟,以允许SD完成任何未完结的操作。对应这些额外时钟的输入数据必须全为1。识别阶段的时钟频率必须限定在400kHz以内,但SD卡一经识别后,时钟频率便可提高到25MHz。
MAXQ2000的SPI模块
MAXQ2000包含一个硬件SPI模块,可以方便地针对SD卡接口进行配置。为了配置时钟极性和数据长度,需将SPICF寄存器置为全零。这种SPI模块配置在时钟的上升沿锁存数据,并将数据长度设置为8位。对于本应用,MAXQ2000的系统时钟频率为16MHz。在这种情况下,需要将SPICK寄存器置为0x28,从而使SPI时钟频率接近380kHz。必须将SPICN寄存器的低2位置位,以使能SPI主机模式。SD SPI数据格式
SD卡的SPI协议与SD总线协议相似。如果一片SD卡没有数据要发送,则将DO引脚保持在全1的空闲状态,因此不是在每个时钟沿都从SD卡的DO引脚接收有效数据。当SD卡有数据要回送给主机时,要在数据之前先发送一些以0为起始位的特定令牌。当这些令牌发送完毕之后,SD卡要发送的所有定长数据立即被发送出去。由于接收器事先已经知道要接收的字节数,因而响应中不包含表征长度的字节。此外,由于在起始令牌和数据都发送完毕后才会进入空闲状态,所以全部数据字节都以不带前缀的原始形式发送。和总线上其它所有通信过程一样,令牌大小也要和SPI传输的8位边界对齐。主机发送给SD卡的指令和数据都遵循类似的格式,以全1指示总线空闲。除了状态令牌以外,所有传输都由附加在数据末尾的循环冗余校验(CRC)码进行保护。系统提供两种CRC算法:CRC-7用于小数据块,CRC-16则用于大数据块。CRC是SD SPI接口的可选部分,但除非应用系统限制它的使用,否则应该使用CRC来确保数据的完整性。循环冗余校验
CRC算法通常用于检测由不可靠的通信通道引起的误差。特定CRC类型的选择根据需要保护的数据长度来决定。对于基于SD存储介质的数据,采用CRC-7和CRC-16编码方式。CRC算法将被保护的数据用选中的除数进行除法运算,产生一个余数。因为该算法中用得的是多项式,所以该除法运算不含进位逻辑。无需考虑进位时,除法运算可通过逻辑XOR操作来实现。所选中的除数通常用CRC的多项式来表示。接着,计算出的余数和数据一起传输,接收器用此余数来检查确认数据在传输过程中是否正常。
对于CRC-7,余数可通过一个7位移位寄存器在软件中计算。计算开始时,将该移位寄存器初始化置为全零。当受保护数据的每一位(MSB在先)被移入移位寄存器的LSB时,移出移位寄存器的MSB,并进行检查。如果移出的位为1,则用CRC-7多项式系数0x09进行异或运算,以此来修正移位寄存器的内容。如果从移位寄存器中移出的位为0,则无需XOR操作。受保护数据的最后一位被移入移位寄存器且完成了条件XOR操作后,必须按此类似方式移入7个或更多0。这一过程称作扩张并完成多项式除法运算。此时,CRC-7值可从移位寄存器直接读出。
图2. 通过移位寄存器架构计算CRC-7。
当接收器收到所有受保护的数据后,接收器可计算基于受保护数据的CRC-7值并将改值与接收到的CRC-7值进行比较。如果这两个值不同,接收器就能判断出受保护数据在传输过程中出现错误。如果这两个值相同,则接收器可完全判定通信通道上的数据是完整的。
CRC-16算法可用同样的方式来构建。在这种情况下,移位寄存器长度为16位而不是7位;多项式系数改为0x1021,且输入数据通过16个0位来扩张。
SD命令格式
发送给SD卡的命令采用6字节的格式(图3)。命令的第1个字节可通过将6位命令码与16进制码0x40进行或运算得到。如果命令需要,则在接下来的4个字节中提供一个32位的参数;最后1个字节包含了从第1个字节到第5个字节的CRC-7校验和。表1列出了一些重要的SD命令。图3. 发送给存储卡的SPI模式SD命令采用6字节格式。
表1. 部分SD存储卡命令
Command | Mnemonic | Argument | Reply | Description |
0 (0x00) | GO_IDLE_STATE | none | R1 | Resets the SD card. |
9 (0x09) | SEND_CSD | none | R1 | Sends card-specific data. |
10 (0x0a) | SEND_CID | none | R1 | Sends card identification. |
17 (0x11) | READ_SINGLE_BLOCK | address | R1 | Reads a block at byte address. |
24 (0x18) | WRITE_BLOCK | address | R1 | Writes a block at byte address. |
55 (0x37) | APP_CMD | none | R1 | Prefix for application command. |
59 (0x3b) | CRC_ON_OFF | Only Bit 0 | R1 | Argument sets CRC on (1) or off (0). |
41 (0x29) | SEND_OP_COND | none | R1 | Starts card initialization. |
将SD卡初始化为SPI模式
刚上电时,SD卡缺省使用专有的SD总线协议。为了将SD卡切换到SPI模式,主机应发出命令0 (GO_IDLE_STATE)。SD卡会检测到SPI模式选择信息,因为卡选择(CS)引脚在该命令和其它所有SPI命令传送过程中都保持为低电平。SD卡以R1响应(图4)作为回应。空闲状态位被置为高电平,表明SD卡已进入空闲状态。为了保持与MMC卡的兼容性,此阶段的SPI时钟频率一定不能超过400kHz。图4. R1响应指示发出的命令是否成功执行。
SD卡进入SPI模式后,SD规范要求主机在进行其它任何请求之前先发送一条初始化命令。为了能区分MMC卡和SD卡,SD卡采用了一种不同的初始化命令,MMC卡对该命令是不响应的。先向卡发送命令55 (APP_CMD),紧接着再发送应用命令41 (SEND_OP_COND),这样即完成了这个重要的步骤。MMC卡对命令55不做回应,通过这一点可鉴别出MMC卡,并将其视作无效介质而拒绝访问。这个命令序列要一直重复执行,直到来自存储卡的R1响应中所有位均为0 (也就是说,IDLE位变为低)才停止。
清单1. 代码必须用SEND_OP_COND来识别SD和MMC卡。
SD卡包含了一些重要的寄存器,用来提供SD卡的相关信息。最重要的寄存器是存储卡特定数据寄存器(CSD)。对于我们的应用示例而言,我们感兴趣的是存储器的数据块大小和总容量。我们还必须对存储卡标识数据寄存器(CID)加以注意,因为它包含了存储卡的制造商详细信息和序列号。图5显示了CSD寄存器和CID寄存器的配置结构。
图5. CSD寄存器和CID寄存器提供SD卡的相关信息。
检查SD卡的响应
要读取存储卡的寄存器或数据块,我们首先必须理解存储卡如何响应我们的请求。在SPI模式下,SD卡以R1应答SEND_CSD (9)、SEND_CID (10)和READ_SINGLE_BLOCK (17)命令。接着则是一个起始令牌,然后是所请求的数据,最后是数据的CRC-16校验和。我们不能想当然地认为数据起始令牌是紧接着R1响应即刻发出的,因为总线在这两个事件之间会进入空闲状态一段时间。图6显示了数据响应的细节。图6. 从SD卡到主机的数据传输要加入一个起始令牌作为前缀。
读取CSD寄存器和CID寄存器的元数据
使用SEND_CSD和SEND_CID命令可返回寄存器的内容,以便确定SD卡的参数。这些命令分别返回与CSD或CID寄存器容量大小一致的固定数量的字节。SEND命令字节中包含的参数被SD卡忽略。从SD卡中读取一个数据块
从SD卡中读取一个数据块是相当简单的。主机发出READ_SINGLE_BLOCK命令,并将起始字节地址作为参数。这个地址必须和介质上一个块的起始位置对齐。然后SD卡会验证这个字节地址,并以一个R1命令作为响应。如果命令中的地址越界,则会在命令响应中指示这种情况。如果完成了SD介质的读取操作并且没有错误发生,则先发送一个起始数据令牌,接着是固定数量的数据,最后是两个字节的CRC-16校验和。如果SD卡碰到硬件故障或介质读取错误,则不会发送起始数据令牌。而是发送一个错误令牌,数据传输随之中止。
向SD卡中写入一个数据块
写入一个数据块和读取数据块类似,即主机必须提供一个与SD卡数据块边界对齐的字节地址。写入数据块的大小必须与READ_BL_LEN相同,一般为512字节。通过发出WRITE_BLOCK (24)命令启动写操作过程,SD卡将以R1命令响应格式进行应答。如果命令响应表明写操作可以进行,则主机发送数据起始令牌,接着是固定数量的数据字节,最后以发送数据的CRC-16校验和结束。SD卡返回一个数据响应令牌以指示待写入的数据是否被接受。如果数据被接受,SD卡会在存储卡忙时始终将DO线保持为低电平。存储卡忙期间,主机不必始终将卡选择线保持为低电平,如果解除CS选择状态,SD卡将释放DO线。当多于一个的设备与SPI总线连接时,上述处理方式非常有用。主机可以一直等待SD卡释放忙指示标志,也可以定期触发片选信号以检查存储卡的工作状态。如果卡仍然处于忙状态,它会将DO线拉低以指示该状态。否则,存储卡会使DO线返回至空闲状态(见图7)。
图7. 从主机到SD卡的数据传输使用一套更为复杂的握手机制。
SPI命令与数据错误检测
可利用CRC-7和CRC-16校验来检测主机与SD卡间的通信错误。如果因物理因素而导致错误发生,如在插入、移除时的触点抖动,或是可拆卸介质固有的接触不良状况,错误检测机制可实现坚固的错误恢复功能。我们强烈建议使用校验和机制,这可以通过发出CRC_ON_OFF (59)命令并将参数的最低位置为高来启动该功能。清单2. 强烈推荐使能CRC校验和。
评论
查看更多