STM32F4:使用 FatFs 和 USB 的 SD 卡失败
STM32F4: SD-Card using FatFs and USB fails
(也在 SE: Electrical Engineering 上询问)
在我的应用程序中,我设置了一个 STM32F4、SD 卡和 USB-CDC(都带有 CubeMX)。
使用 PC,我向 STM32 发送命令,然后它在 SD 卡上执行操作。
这些命令是使用 "communicationBuffer"(由我实现)处理的,它等待通过 USB、UART 等发出的命令...并在收到 \n
字符时设置一个标志。主循环轮询此标志,如果已设置,解析器将处理该命令。到目前为止,还不错。
当我通过 UART 发送命令时,它工作正常,我可以毫无问题地获取 SD 卡上的文件列表或通过 FatFs 执行其他访问。
当我通过 USB-CDC 接收命令时出现问题。解析器按预期工作,但 FatFs 在 f_opendir
中声明 FR_NO_FILESYSTEM (13)
。
其他 FatFs 命令也因此错误代码而失败。
一个USB命令失败后,通过UART的命令也会失败。似乎 USB 以某种方式使初始化的 SD 卡驱动程序崩溃。
知道如何解决此问题吗?还是调试的起点?
我的 USB 实现:
我使用的是CubeMX,所以使用规定的方式初始化USB-CDC接口:
main() 调用 MX_USB_DEVICE_Init(void)
.
在 usbd_conf.c
我有:
void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(pcdHandle->Instance==USB_OTG_FS)
{
/* USER CODE BEGIN USB_OTG_FS_MspInit 0 */
/* USER CODE END USB_OTG_FS_MspInit 0 */
/**USB_OTG_FS GPIO Configuration
PA11 ------> USB_OTG_FS_DM
PA12 ------> USB_OTG_FS_DP
*/
GPIO_InitStruct.Pin = OTG_FS_DM_Pin|OTG_FS_DP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(OTG_FS_IRQn, 7, 1);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
/* USER CODE BEGIN USB_OTG_FS_MspInit 1 */
/* USER CODE END USB_OTG_FS_MspInit 1 */
}
}
接收过程在usbd_cdc_if.c
中实现如下:
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
mRootObject->mUsbBuffer->fillBuffer(Buf, *Len);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
/* USER CODE END 6 */
}
fillBuffer
实现如下(我对 UART 和 USB 传输使用相同的实现 - 为各自的接口使用单独的实例。mBuf
是类型 [=22= 的实例变量]):
void commBuf::fillBuffer(uint8_t *buf, size_t len)
{
// Check if last fill has timed out
if(SystemTime::getMS() - lastActionTime > timeout) {
mBuf.clear();
}
lastActionTime = SystemTime::getMS();
// Fill new content
mBuf.insert(mBuf.end(), buf, buf + len);
uint32_t done = 0;
while(!done) {
for(auto i = mBuf.end() - len, ee = mBuf.end(); i != ee; ++i) {
if(*i == '\n') {
newCommand = true;
myCommand = std::string((char*) &mBuf[0],i - mBuf.begin() + 1);
mBuf.erase(mBuf.begin(), mBuf.begin() + (i - mBuf.begin() + 1));
break;
}
}
done = 1;
}
}
我解决了问题:
在 usb_cdc_if.c
中,#define APP_RX_DATA_SIZE
被设置为 4
(出于某种未知原因)。由于这低于数据包大小,因此大于 4 字节的传入数据包会覆盖我的内存。
碰巧,我记忆的以下部分是 FATFS* FatFs[]
指向已初始化 FATFS 文件系统结构的指针列表。
因此,当 5 个或更多字节的命令到达时,此结构的地址随后被覆盖。
呸,那是一个艰难的过程。
(也在 SE: Electrical Engineering 上询问)
在我的应用程序中,我设置了一个 STM32F4、SD 卡和 USB-CDC(都带有 CubeMX)。 使用 PC,我向 STM32 发送命令,然后它在 SD 卡上执行操作。
这些命令是使用 "communicationBuffer"(由我实现)处理的,它等待通过 USB、UART 等发出的命令...并在收到 \n
字符时设置一个标志。主循环轮询此标志,如果已设置,解析器将处理该命令。到目前为止,还不错。
当我通过 UART 发送命令时,它工作正常,我可以毫无问题地获取 SD 卡上的文件列表或通过 FatFs 执行其他访问。
当我通过 USB-CDC 接收命令时出现问题。解析器按预期工作,但 FatFs 在 f_opendir
中声明 FR_NO_FILESYSTEM (13)
。
其他 FatFs 命令也因此错误代码而失败。
一个USB命令失败后,通过UART的命令也会失败。似乎 USB 以某种方式使初始化的 SD 卡驱动程序崩溃。
知道如何解决此问题吗?还是调试的起点?
我的 USB 实现:
我使用的是CubeMX,所以使用规定的方式初始化USB-CDC接口:
main() 调用 MX_USB_DEVICE_Init(void)
.
在 usbd_conf.c
我有:
void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(pcdHandle->Instance==USB_OTG_FS)
{
/* USER CODE BEGIN USB_OTG_FS_MspInit 0 */
/* USER CODE END USB_OTG_FS_MspInit 0 */
/**USB_OTG_FS GPIO Configuration
PA11 ------> USB_OTG_FS_DM
PA12 ------> USB_OTG_FS_DP
*/
GPIO_InitStruct.Pin = OTG_FS_DM_Pin|OTG_FS_DP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_USB_OTG_FS_CLK_ENABLE();
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(OTG_FS_IRQn, 7, 1);
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
/* USER CODE BEGIN USB_OTG_FS_MspInit 1 */
/* USER CODE END USB_OTG_FS_MspInit 1 */
}
}
接收过程在usbd_cdc_if.c
中实现如下:
static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
mRootObject->mUsbBuffer->fillBuffer(Buf, *Len);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
return (USBD_OK);
/* USER CODE END 6 */
}
fillBuffer
实现如下(我对 UART 和 USB 传输使用相同的实现 - 为各自的接口使用单独的实例。mBuf
是类型 [=22= 的实例变量]):
void commBuf::fillBuffer(uint8_t *buf, size_t len)
{
// Check if last fill has timed out
if(SystemTime::getMS() - lastActionTime > timeout) {
mBuf.clear();
}
lastActionTime = SystemTime::getMS();
// Fill new content
mBuf.insert(mBuf.end(), buf, buf + len);
uint32_t done = 0;
while(!done) {
for(auto i = mBuf.end() - len, ee = mBuf.end(); i != ee; ++i) {
if(*i == '\n') {
newCommand = true;
myCommand = std::string((char*) &mBuf[0],i - mBuf.begin() + 1);
mBuf.erase(mBuf.begin(), mBuf.begin() + (i - mBuf.begin() + 1));
break;
}
}
done = 1;
}
}
我解决了问题:
在 usb_cdc_if.c
中,#define APP_RX_DATA_SIZE
被设置为 4
(出于某种未知原因)。由于这低于数据包大小,因此大于 4 字节的传入数据包会覆盖我的内存。
碰巧,我记忆的以下部分是 FATFS* FatFs[]
指向已初始化 FATFS 文件系统结构的指针列表。
因此,当 5 个或更多字节的命令到达时,此结构的地址随后被覆盖。
呸,那是一个艰难的过程。