|
|
本帖最后由 Winston 于 2026-1-4 15:56 编辑
近期仿照H7 Tool 实现了一下存储功能部分的设计, 因为项目上有需求要用到传感器的数据存储, 之前都是拿SD卡直接保存的, 但是有可能写入失败或因为震动导致连接不稳定. 准备切换到EMMC方案. 在USB MSC上碰到了不对劲的地方. MSC测速非常慢, 远远达不到正常测速的速度.
使用了STM32H743VI作为主处理器, 三星EMMC KLMBG2JETD-B041, 配合USB3300 做高速USB设备的方式.
[C] 纯文本查看 复制代码 void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 13;
RCC_OscInitStruct.PLL.PLLN = 480;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 20;
RCC_OscInitStruct.PLL.PLLR = 4;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
/** Enables the Clock Security System
*/
HAL_RCC_EnableCSS();
}
外部晶振26M, 主频480M, SDMMC1,2是PLL2R 即200MHZ. 在SDMMC中分频为2, 实际得到的频率 SDMMC_CK frequency = sdmmc_ker_ck / 4 = 50M, 应该已经到外设能够支持最大的上限.
开启对应的硬件流控. 开启CaChe.
使用片内测速代码, 测试得到的速度为:
这个速度跟硬汉哥的测试结果类似, 我的可能偏慢一些.
使能USB MSC, 设置MSC缓冲为32KB
数据读取和写入函数如下:
[C] 纯文本查看 复制代码 /**
* @brief Reads data from the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Read_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 13 */
int8_t ret = USBD_FAIL;
uint8_t cnt = 0;
uint32_t timeout = 1000;
HAL_StatusTypeDef status = HAL_MMC_ReadBlocks(&hmmc1, buf, blk_addr, blk_len, timeout);
if (status == HAL_OK)
{
// printf("[USB MSC] HAL_MMC_ReadBlocks: OK\r\n");
ret = USBD_OK;
// 等待卡完成传输
while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER)
{
;
}
}
else
{
// 打印失败的状态码
printf("[USB MSC] HAL_MMC_ReadBlocks: FAIL, status=%d\r\n", status);
// 获取并打印下卡状态
printf("[USB MSC] CardState after fail: %d\r\n", HAL_MMC_GetCardState(&hmmc1));
// 如果有详细错误原因,可以读取错误寄存器
printf("[USB MSC] ErrorCode: 0x%08lX\r\n", HAL_MMC_GetError(&hmmc1));
}
return ret;
/* USER CODE END 13 */
}
/**
* @brief Writes data into the medium.
* @param lun: Logical unit number.
* @param buf: data buffer.
* @param blk_addr: Logical block address.
* @param blk_len: Blocks number.
* @retval USBD_OK if all operations are OK else USBD_FAIL
*/
int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
/* USER CODE BEGIN 14 */
int8_t ret = USBD_FAIL;
uint8_t cnt = 0;
uint32_t timeout = 5000;
HAL_StatusTypeDef status = HAL_MMC_WriteBlocks(&hmmc1, buf, blk_addr, blk_len, timeout);
if (status == HAL_OK)
{
// printf("[USB MSC] HAL_MMC_ReadBlocks: OK\r\n");
ret = USBD_OK;
// 等待卡完成传输
while (HAL_MMC_GetCardState(&hmmc1) != HAL_MMC_CARD_TRANSFER)
{
;
}
}
else
{
// 打印失败的状态码
printf("[USB MSC] HAL_MMC_ReadBlocks: FAIL, status=%d\r\n", status);
// 获取并打印下卡状态
printf("[USB MSC] CardState after fail: %d\r\n", HAL_MMC_GetCardState(&hmmc1));
// 如果有详细错误原因,可以读取错误寄存器
printf("[USB MSC] ErrorCode: 0x%08lX\r\n", HAL_MMC_GetError(&hmmc1));
}
return ret;
/* USER CODE END 14 */
}
/**
* @brief Returns the Max Supported LUNs.
* @param None
* @retval Lun(s) number.
*/
int8_t STORAGE_GetMaxLun_HS(void)
{
/* USER CODE BEGIN 15 */
return (STORAGE_LUN_NBR - 1);
/* USER CODE END 15 */
}
实际测试得到的结果
这个速度我感觉太慢了, 请问大家可能在那里出现了问题呢? 是否需要将写入改为DMA模式呢?
我看USB整体的写入和读取调度都是在中断中完成的, 这里启用DMA似乎也没有任何意义, CPU还是需要死等DMA结束. 请大家赐教
|
|