tag 标签: 小尺寸emmc

相关博文
  • 热度 3
    2024-5-21 17:40
    460 次阅读|
    0 个评论
    目录   引言   SD卡的发展   SD NAND卡的特性与优势   二代SD NAND五大优点   SD NAND六大主要优势   现有产品分类   实际应用场景   SD NAND芯片推荐线路连接:   CSNP4GCR01-AMW的介绍   基础使用例程   例程环境简介   硬件设备及电路   项目创建流程   代码   例程结果   对比市场现有产品   创世半导体(CS)是全球首家推出SD NAND FLASH产品的厂商,SD NAND的出现大大降低了使用 NAND FLASH 的技术难度。   ———————————————— 引言   随着科技的发展,数据的存储需求也在日益增长。在这个信息爆炸的时代,一款高效、稳定、便携的存储设备显得尤为重要。新品SD卡——SD NAND,应运而生,为我们的数据存储带来了新的革命。 SD卡的发展   SD卡自问世以来,其体积不断缩小,容量逐步增大,速度也在不断提升。   开始。   1997年11月,闪迪和英飞凌联合推出了MMC(MultiMediaCard)存储卡。   1999年8月,闪迪又联合松下、东芝推出了SD(Secure Digital)存储卡。SD卡拥有与MMC卡相同的长宽尺寸,略厚一些(2.1mm VS. 1.4mm)。早期SD卡设备/读卡器都能同时兼容MMC卡。   2000年1月,SD卡协会正式成立,当年推出了最大容量64MB、传输速度约12.5MB/s的产品。   2003年3月,闪迪展示了面向手机等移动设备的miniSD卡(目前已退出市场)。   2004年2月,闪迪又和摩托罗拉发布了更小巧的microSD卡(也称为TransFlash或TF卡)。   2005年7月,SD卡协会确认了microSD卡规范,传输速度也提升到了约25MB/s。   2006年1月,SD 2.0带来了采用FAT32文件系统、最大容量32GB的SDHC(包括miniSDHC、microSDHC)卡。而最初版本的SD卡采用FAT12/FAT16文件系统,最大容量为2GB。   2010年5月,SD 3.01带来了采用exFAT文件系统、最大容量提升到2TB的SDXC(包括microSDXC)卡;以及UHS-I高速总线,最大传输速度为104MB/s。   2011年6月,SD 4.0带来了UHS-II总线。这种SD卡(包括microSD卡)具有两排触点,可以实现全双工156MB/s、半双工312MB/s的传输速度。   2016年2月,SD 5.0带来了视频速度等级规范,包括V30、V60、V90。   2016年11月,SD 5.1增加了针对App运行性能的A1标准。在满足10MB/s持续读写的基础上,增加了随机读取1500IOPS、随机写入500IOPS的要求。   2017年2月,SD 6.0带来了全双工312MB/s、全双工624MB/s的UHS-III总线以及随机读取4000IOPS、随机写入2000IOPS的A2标准。UHS-III向下兼容UHS-II,但到目前为止都没有看到任何样品。   2016年11月,SD 5.1增加了针对App运行性能的A1标准。在满足10MB/s持续读写的基础上,增加了随机读取1500IOPS、随机写入500IOPS的要求。   2017年2月,SD 6.0带来了全双工312MB/s、全双工624MB/s的UHS-III总线以及随机读取4000IOPS、随机写入2000IOPS的A2标准。UHS-III向下兼容UHS-II,但到目前为止都没有看到任何样品。   2019年初,闪迪推出“UHS-I超频卡”,突破了104MB/s的速度瓶颈。之后,金士顿、雷克沙等厂商也追加了类似规格的产品。   2020年5月,SD 8.0引入了PCIe 3.0×2、PCIe 4.0×1和PCIe 4.0×2,将最高速度提升至接近4GB/s(3938MB/s)。   2022年5月,SD 9.0增加了快速启动和安全启动特性,为SD卡创造了半嵌入式应用场景。   内存卡在近年来的发展主要集中在提高容量和读写速度上。例如,现在市场上已经出现了容量达到1TB的MicroSD卡,读写速度也不断提高,以满足用户对存储容量和速度的需求。   同时,一些新型内存卡如CFexpress和SD Express也正在逐渐普及,它们支持更快的数据传输速度和更大的容量。随着手机互联网的发展,云存储也逐渐在吞食存储卡的市场。过去需要通过内存卡扩展手机存储空间,现在则可以通过云服务,把数据存储在云端。 SD NAND的特性与优势   以CSNP4GCR01-AMW为例。   不用写驱动程序自带坏块管理的NAND Flash(贴片式TF卡),   尺寸小巧,简单易用,兼容性强,稳定可靠,固件可定制,LGA-8封装,   标准SDIO接口,兼容SPI/SD接口,兼容各大MCU平台,可替代普通TF卡/SD卡,   尺寸6x8mm毫米,机贴手贴都非常方便,   内置SLC晶圆擦写寿命10万次,通过1万次随机掉电测试耐高低温,   支持工业级温度-40°~+85°,   速度级别Class10(读取速度23.5MB/S写入速度12.3MB/S)   标准的SD 2.0协议使得用户可以直接移植标准驱动代码,省去了驱动代码编程环节。   支持TF卡启动的SOC都可以用SD NAND,   提供STM32参考例程及原厂技术支持,   主流容量:128MB/512MB/2GB/4GB/8GB,   比TF卡稳定,比eMMC便宜。 二代SD NAND五大优点   •尺寸小巧   •简单易用   •兼容性强   •稳定可靠   •固件可定制  SD NAND六大主要优势   •LGA-8封装,机贴手贴都方便。   •尺寸小巧5(6*8mm),助力产品颜值提升。   •容量适宜(1Gb/4Gb/32Gb)帮助客户降低成本。   •擦写寿命长(内置SLC晶圆,擦写寿命可达5-10万次,专为嵌式而生)。   •免驱动(即贴即用)直连SD/SPI接口即可使用,已内置Flash管理程序。   •稳定可靠:已通过10k次随机掉电高低温冲击测试。内置FW包含平均读写,坏块管理,垃圾回收等处理机制。   SD NAND 与 TF卡的区别:(看图表) 现有产品分类   本篇示例代码采用工业级CSNP4GCR01-AMW。容量为512MB。 实际应用场景   新一代SD NAND主要应用领域   •5G   •机器人   •智能音箱   •智能面板(HMI)   •移动支付   •智能眼镜(AR)   •智能家居   •医疗设备   •轨道交通   •人脸识别   •3D打印机  SD NAND芯片推荐线路连接:  CSNP4GCR01-AMW的介绍   不用写驱动程序自带坏块管理的NAND Flash(贴片式TF卡),   尺寸小巧,简单易用,兼容性强,稳定可靠,固件可定制,LGA-8封装,   标准SDIO接口,兼容SPI/SD接口,兼容各大MCU平台,可替代普通TF卡/SD卡,   尺寸6x8mm毫米,机贴手贴都非常方便,   内置SLC晶圆擦写寿命10万次,通过1万次随机掉电测试耐高低温,   支持工业级温度-40°~+85°,   速度级别Class10(读取速度23.5MB/S写入速度12.3MB/S)   标准的SD 2.0协议使得用户可以直接移植标准驱动代码,省去了驱动代码编程环节。   支持TF卡启动的SOC都可以用SD NAND,   提供STM32参考例程及原厂技术支持,   主流容量:128MB/512MB/2GB/4GB/8GB,   比TF卡稳定,比eMMC便宜。 基础使用例程   例程环境简介   项目环境:   使用开发板为正点原子探索者STM32F407ZG;   STM32CubeMX;   Keil;   SD NAND:芯片型号 CSNP4GCR01-AMW;芯片转接板(将芯片引脚引出为TF 卡)  硬件设备及电路   SD NAND原理图:   探索者TF 卡槽:   STM32线路连接   使用SDIO模式,   D0接PC8; D1接PC9; D2接PC10; D3接PC11;   信号   SDIO信号“4线模式”   CLK:HOST给DEVICE的时钟信号。   VDD:电源信号。   VSS:Ground信号。   DAT0-DAT3:4条数据线   CMD:用于HOST发送命令和DEVICE回复响应。 项目创建流程   基础时钟配置:   SDIO模式配置:   FATFS配置:   更改缓存区大小:   完成项目其他基础配置。 代码   while(1)之前: FATFS fs; /* FatFs 文件系统对象 */ FIL file; /* 文件对象 */ FRESULT f_res; /* 文件操作结果 */ UINT fnum; /* 文件成功读写数量 */ BYTE ReadBuffer = {0}; /* 读缓冲区 */ BYTE WriteBuffer[] = /* 写缓冲区 */ "This is STM32 working with FatFs \r\n STM32的FATFS文件系统测试 \r\n "; // 在外部 SD 卡挂载文件系统,文件系统挂载时会对 SD 卡初始化 // note:必须先要保证SD卡正常拥有FAT文件系统,如果没有会失败。 f_res = f_mount(&fs, "0:", 1); /*----------------------- 文件系统测试:写测试 -----------------------------*/ /* 打开文件,如果文件不存在则创建它 */ f_res = f_open(&file, "0:FatFs STM32cube.txt", FA_CREATE_ALWAYS | FA_WRITE); if(f_res == FR_OK) { /* 将指定存储区内容写入到文件内 */ f_res = f_write(&file, WriteBuffer, sizeof(WriteBuffer), &fnum); /* 不再读写,关闭文件 */ f_close(&file); } /*------------------- 文件系统测试:读测试 ------------------------------------*/ f_res = f_open(&file, "0:FatFs STM32cube.txt", FA_OPEN_EXISTING | FA_READ); if(f_res == FR_OK) { f_res = f_read(&file, ReadBuffer, sizeof(ReadBuffer), &fnum); } /* 不再读写,关闭文件 */ f_close(&file); /* 不再使用文件系统,取消挂载文件系统 */ f_mount(NULL, "0:", 1); /* 操作完成,停机 */   MX_SDIO_SD_Init()函数中加入 if (HAL_SD_Init(&hsd) != HAL_OK) { Error_Handler(); } if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) { Error_Handler(); } void MX_SDIO_SD_Init(void) { /* USER CODE BEGIN SDIO_Init 0 */ /* USER CODE END SDIO_Init 0 */ /* USER CODE BEGIN SDIO_Init 1 */ /* USER CODE END SDIO_Init 1 */ hsd.Instance = SDIO; hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; hsd.Init.BusWide = SDIO_BUS_WIDE_1B; hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE; hsd.Init.ClockDiv = 34; /* USER CODE BEGIN SDIO_Init 2 */ if (HAL_SD_Init(&hsd) != HAL_OK) { Error_Handler(); } if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) { Error_Handler(); } /* USER CODE END SDIO_Init 2 */ } 例程结果   新建了一个 STM32cube.txt 文件   写入内容如下图所示。   Keil 调试 :成功读取文件内容,暂存至数组中。内容如下   代码解释 对比市场现有产品   目前再嵌入式中使用最多的存储情况:   EEPROM:   只能存放字节类型的数据:芯片为AT24CXX;采用IIC通信,存储内容类型,大小有限。   U盘 :   存放文件格式多样;采用USB接口;占用空间大;可以热拔插;   关于MCU的存储方面,以前基本上用内置的E2PROM,或者是外置的NOR Flash 就可以了。但随着物联网的兴起,MCU的应用越来越广泛了,逐渐的MCU会涉及到大容量的存储需求,用来存储音频,图片(GUI)、视频缓存、协议栈等等。   那传统的E2PROM和NOR Flash就不够用了。这个时候MCU可能就需要用到NAND Flash了。但MCU采用大容量存储芯片NAND Flash,面临着新的挑战。   每个产品都有自己的优缺点。再存储器件选取上,都是考虑项目本身的需求,个产品性能综合考虑最优存储产品。
  • 热度 6
    2023-10-27 17:06
    2099 次阅读|
    0 个评论
    文章目录 FAT32文件系统详细分析 (续FAT文件系统详解) 1. 前言 2. 格式化SD nand/SD卡 3. FAT32文件系统分析 3.1 保留区分析 3.1.1 BPB(BIOS Parameter Block) 及BS区分析 3.1.2 FSInfo 结构扇区分析 3.1.3 引导扇区剩余扇区 3.1.4 备份引导扇区 3.1.5 保留区剩余区域 3.2 分区偏移及大小计算 3.3 FAT区分析: 3.3.1 FAT1 3.3.2 FAT2 3.4 数据区分析: 4. 总结 1. 前言 续上一篇文章 : FATFS文件系统详解:关于如SD卡、SD nand、spi nor flash等众多存储设备 在上一篇文章,我们已经对FAT文件系统有了一个详细的介绍,但由于FAT文件系统由历史发展,存在FAT12/16/32三种系统,在上一篇文章中采用的是FAT16系统作为实例进行的分析,而FAT32系统存在些许差异,且FAT32文件系统在当前应用广泛,因此特补充此篇博文,完善FAT32的示例分析。 2. 格式化SD nand/SD卡 申请到雷龙发展代理的CS创世 贴片 SD Card (SD NAND) 样品,做出测试,分享一下,该公司SD NAND 二代产品介绍可以参考如下地址http://longsto.com/product/list-39.html,有1Gb,4Gb,32Gb,64Gb的容量可选,我这里申请到的是两片32Gb的芯片和测试板. 2.1 格式化SD nand / SD卡,强制采用FAT32格式,分配每个簇大小为2048Byte,同时为了避免其他原有数据干扰,我们此处取消快速格式化。 2.2 使用 WinHex 打开分析 3. FAT32文件系统分析 FAT文件系统布局图如下,和FAT16上有些许差别: 3.1 保留区分析 保留区分为引导扇区、备份引导扇区及其他字段,具体数据段分析如下。 3.1.1 BPB(BIOS Parameter Block) 及BS区分析 BPB及BS参数内容数据如下: EB 58 90 :BS_JmpBoot,跳转指令 4D 53 44 4F 53 35 2E 30:BS_OEMName,MSDOS 5.0,一个名字,指示创建此卷的操作系统,无其他作用` 00 02:BPB_BytsPerSec,扇区大小 512 字节 04:BPB_SecPerClus,每次操作的最小扇区数,簇 Cluster,4 (与格式化时选择的大小匹配 2048 = 512 * 4) 16 11:BPB_RsvdSecCnt,保留区的扇区数,0x1116=4374 (通过此可计算,FAT区起始地址为 4374 * 512 = 0x22 2C00) 02:BPB_NumFATs,FATs的个数,2(一般此值为2,多一个用来做冗余备份,解决系统异常导致第一个损坏时,增大恢复的可能性,表示FAT区有两个FATs备份) 00 00:BPB_RootEntCnt,0,在FAT12/16系统中,此字段表示根目录中32字节目录条目数量,设置此值时需注意对齐,为了最大的兼容性,FAT16系统上此值应设置为512,FAT32系统上此值应设置为0 65536,所以此字段为0) F8:BPB_Media 媒体类型 00 00:BPB_FATSz16,00,一个FAT占用的扇区数,此字段仅在FAT12/16系统使用;FAT32系统,此字段必须为0,使用BPB_FATSz32字段替代。 3F 00:BPB_SecPerTrk,每个磁道的扇区数,此字段仅与具有几何形状且仅用于 IBM PC 的磁盘 BIOS 的介质相关,不用管。 FF 00:BPB_NumHeads,头数量,此字段仅与具有几何形状且仅用于 IBM PC 的磁盘 BIOS 的介质相关,不用管。 00 00 00 00:BPB_HiddSec,0,FAT 卷之前的隐藏物理扇区数(当磁盘被分区之后,当前分区并不一定是从扇区头开始的) 00 08 0F 00:BPB_TotSec32,0x0F0800 = 985088(整个卷空间大小),32位大小区域描述FAT卷扇区总数。 FAT12/16系统,扇区总数小于0x10000时,此字段必须为0,真实值存放在BPB_FATSz16;FAT32系统,此字段一直有效。(481M = 512 * 985088) 以上是FAT12/16/32公共字段,接下来是FAT32独有字段 75 07 00 00:BPB_FATSz32,1909,一个FAT占用的扇区数,FAT区总大小等于 BPB_FATSz?? * BPB_NumFATs 扇区。(由此可计算FAT区总大小:1909 * 2 = 3818扇区 = 3818 * 512Byte = 0x1D D400 Byte) 00 00: BPB_ExtFlags,扩展标识字段,bit7=0,表示所有FAT都是镜像的和活跃的;bit7=1,表示只有bit3-0表示的FAT是有效的。 00 00:BPB_FSVer:FAT32版本,高字节是主版本号,低字节是次版本号。 02 00 00 00:BPB_RootClus,2, 根目录的第一个簇号,此值通常为2,因为前两个簇一般用于保留。 01 00:BPB_FSInfo,1,FSInfo结构扇区与FAT32卷顶部的偏移扇区值。此值通常为1,因为其通常位于引导扇区旁边。 06 00:BPB_BkBootSec,6, 备份引导扇区与FAT32卷顶部的偏移扇区值。此值通常为6,考虑最大的兼容性,此值不建议为其他值。 00 00 00 00 00 00 00 00 00 00 00 00:BPB_Reserved,0,保留 80:BS_DrvNum,IBM PC 的磁盘 BIOS 使用的驱动器号,00h代表软盘,80h代表固定磁盘 00:BS_Reserved,保留字段,0 29:BS_BootSig,扩展引导签名,表示以下存在三个字段 30 D1 B5 78:BS_VolID,与 BS_VolLab 一起构成卷序列号,一般在格式化的时候结合时间生成 4E 4F 20 4E 41 4D 45 20 20 20 20:(解析为:"NO NAME “),BS_VolLab,11byte卷标,当卷标不存在时,此值应设置为"NO NAME” 46 41 54 33 32 20 20 20:BS_FilSysType,始终为"FAT32 ",对FAT类型的确定没有任何影响。 33 C9 ... B9 01 00 00:BS_BootCode32,引导启动程序,与平台有关,不使用时填充为0 BS_BootSign:0xAA55,引导签名,指示这是一个有效的引导扇区当扇区大小大于512字节时,剩余的字段应全部使用0x0填充。 3.1.2 FSInfo 结构扇区分析 FSInfo 数据结构为FAT32系统所特有,其目的是记录FAT32系统上剩余的簇数量以及下一个空闲簇数据;以避免扫描整个磁盘搜索导致的时间浪费。 FSInfo数据偏移可从引导扇区内的 BPB_FSInfo 参数获取,此处为 1,因此 FSInfo 数据偏移为1个扇区,对应512Byte,0x200地址处。FSInfo数据结构如下: 内容如下: 3.1.3 引导扇区剩余扇区 FAT32引导扇区总共有三个512Byte的扇区构成。BPB、BS、FSInfo字段已使用了2个扇区,还剩有一个扇区未使用,字段为0,如下图所示,需要注意的是,此扇区在偏移值510处依旧存在尾部签名0xAA55。 引导扇区剩余字段,为非有效字段,采用0x00填充。 3.1.4 备份引导扇区 相比FAT12/16,FAT32系统上存在引导扇区的备份,此块区域偏移参考引导扇区内BPB_BkBootSec字段,当前引导扇区内此参数值为6, 因此在当前文件系统内,备份引导扇区的偏移为 6号扇区,对应偏移地址为 BPB_BkBootSec * BPB_BytsPerSec = 6 * 512Byte = 3072Byte = 0xC00 3.1.5 保留区剩余区域 在FAT32系统中,保留区除了 BPB区域、FSInfo区域以及这两个区域的备份区域外,还有一部分区域,目前我没找到此区域的作用,我理解为此块区域是作为某种引导程序,数据内容如下: 关于此块区域,欢迎大家在评论区讨论! 此外,还有一处区域的存在也欢迎大家讨论,即FSInfo扇区后面的一个扇区,只有看到尾部签名,其他数据为空,目前也未找到此处有关说明,后续清楚后会在此补充,亦欢迎大家在评论区讨论! 3.2 分区偏移及大小计算 知道BPB参数内容之后,便可以进行分区偏移及大小计算了! 各分区偏移地址及大小如下: 关于FAT区,通常存在一个以上的FAT,如此处所格式化的sd卡便存在两个FAT,对应的偏移地址和大小如下: 注意:在FAT32系统中,根目录区不存在,但依旧存在根目录,不过是根目录作为数据区的一部分! 3.3 FAT区分析: FAT32系统与FAT12/16系统在FAT区数据一个显著差别是:FAT32每条FAT条目占32bit,FAT16占16个bit,FAT12占12bit。关于此部分更详细描述,可参考上一篇:FAT文件系统详解(点击跳转!) 的 4.3 章节! 3.3.1 FAT1 FAT1偏移地址:0x22 2C00 数据内容如下: 3.3.2 FAT2 FAT2是FAT1的备份,偏移地址:0x31 1600 数据内容与FAT1一致,如下: 3.4 数据区分析: 偏移地址:0x40 0000 由参数BPB_RootClus可知,数据区第一个簇是2号簇。 打开数据区的第一个簇,里面存放的内容便是根目录的内容!这也就是为什么FAT32没有根目录区,但依旧存在根目录的实现方式。数据内容如下: 之后我们看到3号簇的内容: 数据字段如下图所示,由于在上一篇博文中已对长短文件名每个字段进行过细致分析,此处不再做过度分析,仅抽取关键字段进行分析,如下图所示: 之后切换到4号簇和5号簇,可以查看到对应数据: 从6号簇开始便没有在使用,均为空闲簇,对应上 FSInfo 结构内 FSI_Nxt_Free 字段的内容。 4. 总结 相比FAT16系统,FAT32文件系统在保留区有了更多的设计: 1)增加了引导扇区的备份,异常掉电等情况下可恢复性更强; 2)增加了FSInfo结构,对于大容量flash访问将更加高效; 此外FAT32系统取消了根目录区,将根目录移至数据区,根目录与普通目录本来就没有什么区别,确实也不用单独分一个区存放,提高了一致性。 关于数据的存储思想,依旧保持不变:FAT区内的FAT条目通过簇链记录扇区使用情况及文件占用的扇区情况;数据区内目录和文件都作为文件,通过目录这一类特殊文件,描述文件属性以及实际文件内容存放的簇的方式,将整个文件管理起来。 综上,便是FAT32格式文件系统的详细解析,欢迎大家评论区进行积极讨论与反馈!!!
  • 热度 6
    2023-2-23 12:01
    584 次阅读|
    0 个评论
    3.2 SPI硬件时序方式 上面的3.1小节是采用SPI模拟时序驱动SD NAND,STM32本身集成有SPI硬件模块,可以直接利用STM32硬件SPI接口读写。 下面贴出底层的适配代码。 上面贴出的驱动代码里,已经将驱动接口部分和协议逻辑部分区分开了,替换底层的SIP读写代码非常方便。 (1)主要替换的代码 /* 函数功能:SPI初始化(模拟SPI) 硬件连接: PB14 PB15 PB13 */ void SPI_Init(void) { /*开启时钟*/ APB1ENR|=1<<14; //开启SPI2时钟 APB2ENR|=1<<3; //PB CRH&=0X000FFFFF; //清除寄存器 CRH|=0XB8B00000; ODR|=0X7<<13; //PB13/14/15上拉--输出高电平 /*SPI2基本配置*/ CR1=0X0; //清空寄存器 CR1|=0<<15; //选择“双线双向”模式 CR1|=0<<11; //使用8位数据帧格式进行发送/接收; CR1|=0<<10; //全双工(发送和接收); CR1|=1<<9; //启用软件从设备管理 CR1|=1<<8; //NSS CR1|=0<<7; //帧格式,先发送高位 CR1|=0x0<<3;//当总线频率为36MHZ时,SPI速度为18MHZ,高速。 CR1|=1<<2; //配置为主设备 CR1|=1<<1; //空闲状态时, SCK保持高电平。 CR1|=1<<0; //数据采样从第二个时钟边沿开始。 CR1|=1<<6; //开启SPI设备。 } /* 函数功能:SPI读写一个字节 */ u8 SPI_ReadWriteOneByte(u8 data_tx) { u16 cnt=0; SR&1<<1)==0) //等待发送区空--等待发送缓冲为空 { cnt++; =65530)return 0; //超时退出 u16=2个字节 } DR=data_tx; //发送一个byte cnt=0; SR&1<<0)==0) //等待接收完一个byte { cnt++; =65530)return 0; //超时退出 } DR; //返回收到的数据 } 函数功能:SD卡底层接口,通过SPI时序向SD卡读写一个字节 函数参数:data是要写入的数据 返 回 值:读到的数据 */ u8 SDCardReadWriteOneByte(u8 DataTx) { return SPI_ReadWriteOneByte(DataTx); } (2)运行效果 3.3 SDIO方式 如果想提高SD NAND的读写速度,可以采用SDIO协议,STM32本身有SDIO的硬件支持,配置好SDIO的寄存器即可完成SD NAND的操作。 SDIO的数据线都比SPI多,读写速度自然没法比的。 下面贴出STM32F103ZE上面编写的SDIO协议读写SD NAND的驱动代码。 (1)整体工程代码 (2)sdio.c #include "sdio_sdcard.h" #include "string.h" #include "sys.h" #include "usart.h" static u8 CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1; //SD卡类型(默认为1.x卡) static u32 CSD_Tab ,CID_Tab ,RCA=0; //SD卡CSD,CID以及相对地址(RCA)数据 static u8 DeviceMode=SD_DMA_MODE; //工作模式,注意,工作模式必须通过SDIO_SdCardSetDeviceMode,后才算数.这里只是定义一个默认的模式(SD_DMA_MODE) static u8 StopCondition=0; //是否发送停止传输标志位,DMA多块读写的时候用到 volatile SDIO_SD_ERROR_INFO TransferError=SD_OK; //数据传输错误标志,DMA读写时使用 volatile u8 TransferEnd=0; //传输结束标志,DMA读写时使用 SD_CardInfo SDCardInfo; //SD卡信息 //SDIO_SdCardReadDiskSector/SDIO_SdCardWriteDiskSector函数专用buf,当这两个函数的数据缓存区地址不是4字节对齐的时候, //需要用到该数组,确保数据缓存区地址是4字节对齐的. __align(4) u8 SDIO_DATA_BUFFER ; /* SD卡与开发板的SDIO方式接线关系如下: DATA0---PC8 DATA1---PC9 DATA2---PC10 DATA3---PC11 CLK-----PC1 CMD-----PD2 */ /* 函数功能:SDIO方式初始化SD卡 返回值 :错误代码;(0,无错误) */ SDIO_SD_ERROR_INFO SDIO_SdCardInit(void) { u8 clkdiv=0; SDIO_SD_ERROR_INFO errorstatus=SD_OK; //SDIO IO口初始化 APB2ENR|=1<<4; //使能PORTC时钟 APB2ENR|=1<<5; //使能PORTD时钟 AHBENR|=1<<10; //使能SDIO时钟 AHBENR|=1<<1; //使能DMA2时钟 CRH&=0XFFF00000; CRH|=0X000BBBBB; //PC.8~12 复用输出 CRL&=0XFFFFF0FF; CRL|=0X00000B00; //PD2复用输出,PD7 上拉输入 //SDIO外设寄存器设置为默认值 POWER=0x00000000; CLKCR=0x00000000; ARG=0x00000000; CMD=0x00000000; DTIMER=0x00000000; DLEN=0x00000000; DCTRL=0x00000000; ICR=0x00C007FF; MASK=0x00000000; STM32_NVIC_SetPriority(SDIO_IRQn,0,0); //SDIO中断配置 errorstatus=SDIO_SdPowerON(); //SD卡上电 SDIO_SdCardInitializeCards(); //初始化SD卡 SDIO_SdCardGetInfo(&SDCardInfo); //获取卡信息 SDIO_SdCardSelectAddr((u32)(SDCardInfo.RCA<<16));//选中SD卡 SDIO_SdCardEnableWideBusOperation(1); //4位宽度,如果是MMC卡,则不能用4位模式 if((errorstatus==SD_OK)||(SDIO_MULTIMEDIA_CARD==CardType)) { if(SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V1_1||SDCardInfo.CardType==SDIO_STD_CAPACITY_SD_CARD_V2_0) { clkdiv=SDIO_TRANSFER_CLK_DIV+6; //V1.1/V2.0卡,设置最高72/12=6Mhz }else clkdiv=SDIO_TRANSFER_CLK_DIV; //SDHC等其他卡,设置最高72/6=12Mhz SDIO_ClockSet(clkdiv); //设置时钟频率,SDIO时钟计算公式:SDIO_CK时钟=SDIOCLK/ ;其中,SDIOCLK固定为48Mhz errorstatus=SDIO_SdCardSetDeviceMode(SD_POLLING_MODE); //设置为查询模式 } return errorstatus; } /* 函数功能: SDIO时钟初始化设置 函数参数: clkdiv:时钟分频系数 CK时钟=SDIOCLK/ ;(SDIOCLK时钟固定为48Mhz) */ void SDIO_ClockSet(u8 clkdiv) { CLKCR; tmpreg&=0XFFFFFF00; tmpreg|=clkdiv; CLKCR=tmpreg; } /* 函数功能: SDIO发送命令函数 函数参数: cmdindex:命令索引,低六位有效 waitrsp:期待的相应.00/10,无响应;01,短响应;11,长响应 arg:参数 */ void SDIO_SendCmd(u8 cmdindex,u8 waitrsp,u32 arg) { u32 tmpreg; ARG=arg; CMD; tmpreg&=0XFFFFF800; //清除index和waitrsp tmpreg|=cmdindex&0X3F; //设置新的index tmpreg|=waitrsp<<6; //设置新的wait rsp tmpreg|=0<<8; //无等待 tmpreg|=1<<10; //命令通道状态机使能 CMD=tmpreg; } /* 函数功能: SDIO发送数据配置函数 函数参数: datatimeout:超时时间设置 datalen:传输数据长度,低25位有效,必须为块大小的整数倍 blksize:块大小.实际大小为:2^blksize字节 dir:数据传输方向:0,控制器到卡;1,卡到控制器; */ void SDIO_SendDataConfig(u32 datatimeout,u32 datalen,u8 blksize,u8 dir) { u32 tmpreg; DTIMER=datatimeout; DLEN=datalen&0X1FFFFFF; //低25位有效 DCTRL; tmpreg&=0xFFFFFF08; //清除之前的设置. tmpreg|=blksize<<4; //设置块大小 tmpreg|=0<<2; //块数据传输 tmpreg|=(dir&0X01)<<1; //方向控制 tmpreg|=1<<0; //数据传输使能,DPSM状态机 DCTRL=tmpreg; } /* 函数功能:卡上电 查询所有SDIO接口上的卡设备,并查询其电压和配置时钟 返回值:错误代码;(0,无错误) */ SDIO_SD_ERROR_INFO SDIO_SdPowerON(void) { u8 i=0; SDIO_SD_ERROR_INFO errorstatus=SD_OK; u32 response=0,count=0,validvoltage=0; u32 SDType=SD_STD_CAPACITY; //配置CLKCR寄存器 CLKCR=0; //清空CLKCR之前的设置 CLKCR|=0<<9; //非省电模式 CLKCR|=0<<10; //关闭旁路,CK根据分频设置输出 CLKCR|=0<<11; //1位数据宽度 CLKCR|=0<<13; //SDIOCLK上升沿产生SDIOCK CLKCR|=0<<14; //关闭硬件流控制 SDIO_ClockSet(SDIO_INIT_CLK_DIV);//设置时钟频率(初始化的时候,不能超过400Khz) POWER=0X03; //上电状态,开启卡时钟 CLKCR|=1<<8; //SDIOCK使能 for(i=0;i<74;i++) { SDIO_SendCmd(SD_CMD_GO_IDLE_STATE,0,0);//发送CMD0进入IDLE STAGE模式命令. errorstatus=SDIO_CmdErrorCheck(); if(errorstatus==SD_OK)break; } if(errorstatus)return errorstatus;//返回错误状态 SDIO_SendCmd(SDIO_SEND_IF_COND,1,SD_CHECK_PATTERN);//发送CMD8,短响应,检查SD卡接口特性. //arg :01,支持电压范围,2.7~3.6V //arg :默认0XAA //返回响应7 errorstatus=SDIO_CmdResp7Error(); //等待R7响应 if(errorstatus==SD_OK) //R7响应正常 { CardType=SDIO_STD_CAPACITY_SD_CARD_V2_0; //SD 2.0卡 SDType=SD_HIGH_CAPACITY; //高容量卡 } SDIO_SendCmd(SD_CMD_APP_CMD,1,0); //发送CMD55,短响应 errorstatus=SDIO_CmdResp1Error(SD_CMD_APP_CMD); //等待R1响应 if(errorstatus==SD_OK)//SD2.0/SD 1.1 { //SD卡,发送ACMD41 SD_APP_OP_COND,参数为:0x80100000 while((!validvoltage)&&(count