我的主板上有这个闪存IC,它连接到我的STM32F04 ARM处理器。处理器的USB端口可供用户使用。我希望通过USB连接到PC时,我的闪存被检测为存储设备。
作为第一步,我在我的程序中将USB类定义为MSC,工作正常。因为当我将我的主板连接到PC时,它会检测到连接的大容量存储设备,并给出错误"您应该在使用它之前格式化光盘"。
现在的问题是,我如何定义我的闪存作为存储'到我的处理器。以下可能是您答案的一部分: -usbd_msc_storage_template.c -FAT文件系统
我使用的是STM32F446处理器。 FREERTOS和FATFS。 我的电脑上有Windows 10。
提前致谢:)
答案 0 :(得分:5)
首先 - 如果您只需要将闪存作为大容量存储设备在PC上显示,那么您就不需要FatFS,因为它用于以逐个文件的方式访问存储MCU。当PC访问存储设备时,它自己管理文件系统,您可以选择在格式化驱动器时使用哪种文件系统。当与存储器本身通信时,它处于低电平状态,它所做的就是告诉存储器从Y地址"读取/写入X字节。所有设备需要做的是写入或读取给定数据并返回操作结果。
USB大容量存储设备类
此USB类将您的设备作为存储设备公开给主机,允许它从/向指定地址读取或写入给定的字节数。对于您已提到的STM32F4,您需要实现的功能如下(基于STM32Cube库):
typedef struct _USBD_STORAGE
{
int8_t (* Init) (uint8_t lun);
int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size);
int8_t (* IsReady) (uint8_t lun);
int8_t (* IsWriteProtected) (uint8_t lun);
int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* GetMaxLun)(void);
int8_t *pInquiry;
}USBD_StorageTypeDef;
正如您所提到的,有USBD_MSC_Template_fops.c / .h
个文件提供了一个示例空模板供您实施,最重要的功能是Read
和Write
"工作"已经完成了。要初始化您的设备,当连接到PC主机时显示为USB大容量存储设备,剩下的就是:初始化USB本身(USBD_Init
),注册MSC设备类(USBD_RegisterClass
),在检测到与主机的连接时,在驱动程序(USBD_MSC_RegisterStorage
)中注册所述结构并启动驱动程序的USB设备进程(USBD_Start
)。有很多例子可以做到这一点 - 参见Discovery或Eval板的参考实现。您似乎已正确完成此操作,因为主机已将您的设备检测为USB MSC设备,并将其报告为未格式化。
您的系统说驱动器未格式化的原因是因为usbd_msc_storage_template.c
文件中的空实现返回STORAGE_Read
函数的成功执行(返回代码0),但实际上并未执行任何读取 - 没有数据被发回。虽然这可能因主机而异,具体取决于操作系统,但最有可能的情况是您要么看到有关存储未格式化或数据损坏的消息。
将USB海量存储设备回调与物理内存连接
如上所述,调用USBD_MSC_RegisterStorage
将在USB MSC设备类驱动程序中注册您的结构。此时,驱动程序本身将在适当的时刻调用您提供的功能 - 无论何时主机请求。如果目标内存是SD卡,自然的步骤是首先实现访问SD卡的功能。一旦这些功能经过测试并证明可以正常工作,剩下的就是将它们放入USB MSC设备Read
和Write
功能中并且 - 假设正确的中断优先级 - 它通常应该工作& #34;开箱即用"。系统应该能够格式化卡,然后通过您的MCU读取和写入文件。
对于您选择的任何类型的内存,它的工作方式相同。唯一的要求是完全按原样实现USBD_StorageTypeDef
回调函数。这意味着主机可以选择在报告的地址空间内的任何地址写入任意数量的随机字节,并且您要么完全服从(按原样写入所有数据)并返回"成功执行"或者返回错误,这很可能意味着您的驱动器将被卸载并且将提示用户输入错误消息。在读取的情况下,这意味着如果主机从Y地址请求X个字节,则设备需要准确地返回该数量的数据。这意味着如果您的内存类型不完全适合这种访问,那么在访问物理内存的层中必须完成更多工作才能遵守USB MSC接口。所有这一切自然导致我们到达下面的最后一点。
闪存作为文件系统存储
对于直接访问原始数据的闪存,存在某些缺点,使它们不能完全适用于文件系统应用程序。那些来自这些记忆的构建方式。虽然可以实现,但为了隐藏这些不完善之处,还需要采取其他措施:
单独编写" 1"直接访问Flash存储器只允许你写" 0"给定地址下的位。一旦某个位被翻转到" 0",它就不能再被一次性地翻回到" 1"。为此,需要首先擦除整个数据块。根据闪存部分的不同,这通常是512,4096等字节的区域。这意味着如果您想将给定字节从1(二进制0000 0001)更改为4(二进制0000 0100),则必须对整个扇区执行读取 - 擦除 - 写入。对你而言,这意味着即使主机请求写入的其中一个位需要从" 0"至" 1",您需要先删除该区域。
随机访问 - 根据内存类型(NOR / NAND),您可能会或可能无法随机访问数据。特别是,对于NOR闪存,您可以单独读取或写入数据,而对于NAND存储器,由于单元如何互连,仅允许页面访问。这意味着您可能必须读取或写入超出必要的数据。
写耐久性 - 闪存每个单元都有一定数量的写周期。这意味着如果您经常将数据写入同一地址,您可能会非常快地超过此限制。这对FAT等文件系统尤为重要,FAT区域将不断写入。这可以通过实现某种形式的磨损均衡来解决,其中物理扇区写入均匀分布。您当然可以选择从IsWriteProtected
返回true,如果您的应用可以使用,则将其设为只读。
现在关于当前SD卡如何实现这一切 - 现在我所知道的所有SD卡都包含一个简单的微控制器(某种8081,ARM7或类似的),它实现了上述所有内容以及SD协议。与卡通话时,您并不真正与原始内存通信,而是与位于您和您的数据之间的MCU进行通信。它的作用是向您展示完美连续数据的幻觉。