2018-05-08 04:11 AM
i using STMF779I-EVAL board and try to implement USB Mass Storage + SD Card . But the read/write speed i am getting when write/read from Window PC is too slow.
Read : 1MB/s; Write : 200KB/s
Even I already used DMA mechanism to speed up the SDMMC driver .
This is my implementation for read/write
int8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{ //printf('STORAGE_Write_HS \n'); HAL_SD_CardStateTypeDef sd_card_state_return; HAL_SD_StateTypeDef state_return; uint32_t timeout = 0; if(HAL_OK != HAL_SD_WriteBlocks_DMA(&hsd1, buf, blk_addr, (uint32_t) blk_len)) { printf('Error : STORAGE_Write_HS failed Err: %u, blk_addr : %u ; blk_len : %u\n', hsd1.ErrorCode, blk_addr, blk_len); return USBD_FAIL; }// Callback
HAL_SD_TxCpltCallback increare writestatus to check writing status
while (writestatus == 0)
{}
writestatus = 0;/* Wait until SD card is ready to use for new operation */
while (HAL_SD_GetCardState(&hsd1) != HAL_SD_CARD_TRANSFER) { } return (USBD_OK); /* USER CODE END 14 */}void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{ //printf('HAL_SD_TxCpltCallback \n'); if(hsd->Instance == SDMMC1) { writestatus = 1; }}
I think that the HAL_SD_GetCardState(0 to long time to change state to HAL_SD_CARD_TRANSFER.
Could you let me know what is the root cause and is there any way to improve the speed ?
Thank you very much.
2018-05-16 02:58 AM
Could somebody help to take a look ?
2018-05-16 06:52 AM
>> STMF779I-EVAL
Sorry not a board that I have.
Would check to see the maximum block requested for read/write operations, and check if descriptors/settings reported to PC limit block count or transfer size.
2018-05-16 09:56 PM
Hi
Turvey.Clive
,I checked block len in functionint8_t STORAGE_Write_HS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
it always write 1 block /time, and block size is 512 bytes.
Is it the problem cause writing slow issue ? and how can i improve this ?
2018-05-16 10:37 PM
STM32Cube_FW_F7_V1.0\Projects\STM32756G_EVAL\Applications\USB_Device\MSC_Standalone\Inc\usbd_conf.h
/* MSC Class Config */
#define MSC_MEDIA_PACKET 512 // Increase as a binary multiple, ie (512 << 1)You might need to make the heap large also
https://community.st.com/0D50X00009XkXa1SAF
>>Is it the problem cause writing slow issue ? and how can i improve this ?
Single block read/write is the worst case scenario for mass storage, high command penalty on each block, designed to stream 32-64KB
2018-05-17 07:15 PM
You'd want to make sure there isn't an issue with using or allocating that much memory. Where it falls in the memory space may also be problematic. Issues with caching, use of DMA, use of DTCMRAM, etc.
If the size is reported somewhere, there might be a 16-bit limit.
32KB should be sufficient, consider the speed the SDMMC is being clocked. Most microSD cards are supported to clock a 50 MHz on the bus (not 24 MHz the 48 MHz gets you).
Check the clock source selected in RCC->DCKCFGR2, you should be able to select the 200 MHz SYSCLK, not the ~48 MHz of the PLL_Q or PLLSAI_P. You'll need to change the SDMMC ClockDiv appropriately.
void plldumpf7(void) //
mailto:sourcer32@gmail.com
{ uint32_t vcoinput, vco; uint32_t oscsource; uint32_t dckcfgr2 = RCC->DCKCFGR2; uint32_t pllcfgr = RCC->PLLCFGR; uint32_t plli2scfgr = RCC->PLLI2SCFGR; uint32_t pllsaicfgr = RCC->PLLSAICFGR; uint32_t pllp, pllq, pllr; uint32_t p, q, r; uint32_t plli2s_p, plli2s_q, plli2s_r; uint32_t pllsai_p, pllsai_q, pllsai_r;/* Configure the PLLSAI division factor */
/* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ if((pllcfgr & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) oscsource = HSI_VALUE; /* In Case the PLL Source is HSI (Internal Clock) */ else oscsource = HSE_VALUE; /* In Case the PLL Source is HSE (External Clock) */vcoinput = (oscsource / (uint32_t)(pllcfgr & RCC_PLLCFGR_PLLM));
vco = (vcoinput * ((pllcfgr & RCC_PLLCFGR_PLLN) >> 6));pllp = (((pllcfgr & RCC_PLLCFGR_PLLP) >> 16) + 1) * 2; // SYSCLK
p = vco / pllp;pllq = (pllcfgr & RCC_PLLCFGR_PLLQ) >> 24; // PLL48
q = vco / pllq;pllr = (pllcfgr & 0x70000000) >> 28; // Not on F74xx RCC_PLLCFGR_PLLR
r = vco / pllr;printf('PLL P:%9d Q:%9d R:%9d\n', p, q, r);
vco = (vcoinput * ((plli2scfgr & RCC_PLLI2SCFGR_PLLI2SN) >> 6));pllq = (((plli2scfgr & RCC_PLLI2SCFGR_PLLI2SP) >> 16) + 1) * 2;
plli2s_p = vco / pllp;pllp = (plli2scfgr & RCC_PLLI2SCFGR_PLLI2SQ) >> 24;
plli2s_q = vco / pllq;pllr = (plli2scfgr & RCC_PLLI2SCFGR_PLLI2SR) >> 28;
plli2s_r = vco / pllr;printf('PLLI2S P:%9d Q:%9d R:%9d\n', plli2s_p, plli2s_q, plli2s_r);
vco = (vcoinput * ((pllsaicfgr & RCC_PLLSAICFGR_PLLSAIN) >> 6));pllq = (((pllsaicfgr & RCC_PLLSAICFGR_PLLSAIP) >> 16) + 1) * 2;
pllsai_p = vco / pllp;pllp = (pllsaicfgr & RCC_PLLSAICFGR_PLLSAIQ) >> 24; // 2..15
pllsai_q = vco / pllq;pllr = (pllsaicfgr & RCC_PLLSAICFGR_PLLSAIR) >> 28; // 2..7
pllsai_r = vco / pllr;printf('PLLSAI P:%9d Q:%9d R:%9d\n', pllsai_p, pllsai_q, pllsai_r);
// DCKCFGR2 bit 27 PLL48CLK 0=PLLQ, 1=SAIP
// DCKCFGR2 bit 28 SDMMCSEL 0=PLL48, 1=SYSCLK (bit 29 for SDMMC2) { uint32_t pll48clk = ((dckcfgr2 & (1<<27)) ? pllsai_p : q); uint32_t sdmmc_clkcr = SDMMC1->CLKCR; uint32_t sdclk = ((dckcfgr2 & (1<<28)) ? p : pll48clk) / ((sdmmc_clkcr & 0xFF) + 2); printf('PLL48CLK %9d, %6.2lf MHz\n', pll48clk, (double)pll48clk*1e-6); printf('SDCLK %9d, %6.2lf MHz\n', sdclk, (double)sdclk*1e-6); }{
uint32_t dckcfgr1 = RCC->DCKCFGR1; uint32_t divr = 2 << ((dckcfgr1 & RCC_DCKCFGR1_PLLSAIDIVR) >> 16); // 2,4,8,16 uint32_t lcdclk = pllsai_r / divr; printf('LCDCLK %9d, %6.2lf MHz\n', lcdclk, (double)lcdclk*1e-6); }}>>Could you help me on this issue ?
Consider sponsoring my work/projects.
2018-05-17 08:41 PM
Dear
Turvey.Clive.002
,Many thanks for for your support , now i can improve the writing speed to 2.5 MB/s on STM32F779 eval board.
by change to#define MSC_MEDIA_PACKET 32768
But i want to improve more then i changeMSC_MEDIA_PACKET to 65536 but can not read/write SDCard any more.
I already check the USB descriptor it define the USB MAX packet size is 64
__ALIGN_BEGIN uint8_t USBD_HS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END =
{ 0x12, /*bLength */ USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ #if (USBD_LPM_ENABLED == 1) 0x01, /*bcdUSB */ /* changed to USB version 2.01 in order to support LPM L1 suspend resume test of USBCV3.0*/ #else 0x00, /*bcdUSB */ #endif /* (USBD_LPM_ENABLED == 1) */0x02,
0x00, /*bDeviceClass*/ 0x00, /*bDeviceSubClass*/ 0x00, /*bDeviceProtocol*/ USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ // This is 64 LOBYTE(USBD_VID), /*idVendor*/ HIBYTE(USBD_VID), /*idVendor*/ LOBYTE(USBD_PID_HS), /*idProduct*/ HIBYTE(USBD_PID_HS), /*idProduct*/ 0x00, /*bcdDevice rel. 2.00*/ 0x02, USBD_IDX_MFC_STR, /*Index of manufacturer string*/ USBD_IDX_PRODUCT_STR, /*Index of product string*/ USBD_IDX_SERIAL_STR, /*Index of serial number string*/ USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ };So I suspect whether the Window host PC doesn't support packet size 64or any issue from the USB storage driver from firmware side ?
Could you help me on this issue ?
2018-05-17 10:00 PM
Dear
Turvey.Clive.002
,It actually the is a warning compiler when i set MSC_MEDIA_PACKET to 65536
Look intousbd_msc_scsi.c there is 1 functionSCSI_Read10() itset hmsc->bot_data_length = MSC_MEDIA_PACKET; but
bot_data_length is declared uint16_t only.
So can i say that the current ST USB stack only support 32KB ?
Consider sponsoring my work/projects.
What do you mean
2018-05-18 10:36 AM
I'm not paid by ST, if I've saved you man-hours or man-days of work, consider how you can help me.
2018-05-18 03:22 PM
On the STM32F769I-DISCO I had similar issues, the example code was very slow. Writes corrupted the card too.
I have fixed the write corruption (must check no longer busy before returning) and boosted read speed to over 7MB/sec.
My approach was to implement a simple read-cache and read in numerous blocks in one go.
i.e. instead of requesting as single 512 byte sectors, I read 32x 512 byte sectors, store the result to RAM and then return a pointer to the start of the sector. On the next read, if that sector is already in RAM, I just return a pointer and don't do an SDcard read. This makes a BIG difference. Any writes invalidate the cache valid flag.
I also found that the provided SD card read block code is issuing an initialisation command every time, that is not required and wastes time.
I'm afraid I'm not sharing the code, but hopefully these notes should give you a start.
James