Allregia 9 11 сентября, 2012 Опубликовано 11 сентября, 2012 · Жалоба Похоже у Вас не работает как положено мультиблоковая запись. Если используете драйвер SDIO от ST, Да, его. то гляньте там между записью блоков в команде CMD25 имеется задержка, у меня тоже скорость была очень низкая, пока я эту задержку не покоцал. Там зачемто сделано ожидание перед опросом состояния записи -возможно чтобы не прерывать процессы в контроллере карты. Вообщем я ее уменьшил в несколько раз и скорость записи теперь достаточно стабильна и пропорциональна только классу карты Не пойму где именно надо покоцать. Вот процедура блочной записи: SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) { SD_Error errorstatus = SD_OK; TransferError = SD_OK; TransferEnd = 0; StopCondition = 1; SDIO->DCTRL = 0x0; if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) { BlockSize = 512; WriteAddr /= 512; } SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE); SDIO_DMACmd(ENABLE); SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, (NumberOfBlocks * BlockSize)); /* Set Block Size for Card */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); if (SD_OK != errorstatus) { return(errorstatus); } /*!< To improve performance */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) (RCA << 16); SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_APP_CMD); if (errorstatus != SD_OK) { return(errorstatus); } /*!< To improve performance */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)NumberOfBlocks; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCK_COUNT; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SET_BLOCK_COUNT); if (errorstatus != SD_OK) { return(errorstatus); } /*!< Send CMD25 WRITE_MULT_BLOCK with argument data address */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)WriteAddr; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_MULT_BLOCK; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK); if (SD_OK != errorstatus) { return(errorstatus); } SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT; SDIO_DataInitStructure.SDIO_DataLength = NumberOfBlocks * BlockSize; SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4; SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard; SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; SDIO_DataConfig(&SDIO_DataInitStructure); return(errorstatus); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 12 сентября, 2012 Опубликовано 12 сентября, 2012 · Жалоба Да, его. Не пойму где именно надо покоцать. Вот процедура блочной записи: Хм..странно, в Вашей версии практически никакие проверки не делаются. У меня наверно постарей чутка версия: * @file stm32_eval_sdio_sd.c * @author MCD Application Team * @version V4.4.0 * @date 31-December-2010 SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) { SD_Error errorstatus = SD_OK; uint8_t power = 0, cardstate = 0; uint32_t bytestransferred = 0; uint32_t restwords = 0; uint32_t *tempbuff = (uint32_t *)writebuff; __IO uint32_t count = 0; if (writebuff == NULL) { errorstatus = SD_INVALID_PARAMETER; return(errorstatus); } TransferError = SD_OK; TransferEnd = 0; TotalNumberOfBytes = 0; SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT; SDIO_DataInitStructure.SDIO_DataLength = 0; SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_1b; SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard; SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Disable; SDIO_DataConfig(&SDIO_DataInitStructure); SDIO_DMACmd(DISABLE); if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED) { errorstatus = SD_LOCK_UNLOCK_FAILED; return(errorstatus); } if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) { BlockSize = 512; WriteAddr /= 512; } /*!< Set the block size, both on controller and card */ if ((BlockSize > 0) && (BlockSize <= 2048) && ((BlockSize & (BlockSize - 1)) == 0)) { power = convert_from_bytes_to_power_of_two(BlockSize); SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); if (errorstatus != SD_OK) { return(errorstatus); } } else { errorstatus = SD_INVALID_PARAMETER; return(errorstatus); } /*!< Wait till card is ready for data Added */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) (RCA << 16); SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_STATUS; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SEND_STATUS); if (errorstatus != SD_OK) { return(errorstatus); } if (NumberOfBlocks > 1) { /*!< Common to all modes */ if (NumberOfBlocks * BlockSize > SD_MAX_DATA_LENGTH) { errorstatus = SD_INVALID_PARAMETER; return(errorstatus); } if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)) { /*!< To improve performance */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) (RCA << 16); SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_APP_CMD); if (errorstatus != SD_OK) { return(errorstatus); } /*!< To improve performance */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)NumberOfBlocks; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCK_COUNT; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_SET_BLOCK_COUNT); if (errorstatus != SD_OK) { return(errorstatus); } } /*!< Send CMD25 WRITE_MULT_BLOCK with argument data address */ SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)WriteAddr; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_MULT_BLOCK; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK); if (SD_OK != errorstatus) { return(errorstatus); } TotalNumberOfBytes = NumberOfBlocks * BlockSize; StopCondition = 1; SrcBuffer = (uint32_t *)writebuff; SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT; SDIO_DataInitStructure.SDIO_DataLength = NumberOfBlocks * BlockSize; SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) power << 4; SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard; SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; SDIO_DataConfig(&SDIO_DataInitStructure); if (DeviceMode == SD_POLLING_MODE) { while (!(SDIO->STA & (SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DATAEND | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_STBITERR))) { if (SDIO_GetFlagStatus(SDIO_FLAG_TXFIFOHE) != RESET) { if (!((TotalNumberOfBytes - bytestransferred) < SD_HALFFIFOBYTES)) { for (count = 0; count < SD_HALFFIFO; count++) { SDIO_WriteData(*(tempbuff + count)); } tempbuff += SD_HALFFIFO; bytestransferred += SD_HALFFIFOBYTES; } else { restwords = ((TotalNumberOfBytes - bytestransferred) % 4 == 0) ? ((TotalNumberOfBytes - bytestransferred) / 4) : ((TotalNumberOfBytes - bytestransferred) / 4 + 1); for (count = 0; count < restwords; count++, tempbuff++, bytestransferred += 4) { SDIO_WriteData(*tempbuff); } } } } if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET) { SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT); errorstatus = SD_DATA_TIMEOUT; return(errorstatus); } else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET) { SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL); errorstatus = SD_DATA_CRC_FAIL; return(errorstatus); } else if (SDIO_GetFlagStatus(SDIO_FLAG_TXUNDERR) != RESET) { SDIO_ClearFlag(SDIO_FLAG_TXUNDERR); errorstatus = SD_TX_UNDERRUN; return(errorstatus); } else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET) { SDIO_ClearFlag(SDIO_FLAG_STBITERR); errorstatus = SD_START_BIT_ERR; return(errorstatus); } if (SDIO_GetFlagStatus(SDIO_FLAG_DATAEND) != RESET) { if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)) { /*!< Send CMD12 STOP_TRANSMISSION */ SDIO_CmdInitStructure.SDIO_Argument = 0x0; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_STOP_TRANSMISSION; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&SDIO_CmdInitStructure); errorstatus = CmdResp1Error(SD_CMD_STOP_TRANSMISSION); if (errorstatus != SD_OK) { return(errorstatus); } } } } else if (DeviceMode == SD_INTERRUPT_MODE) { SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_TXFIFOHE | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR, ENABLE); while ((TransferEnd == 0) && (TransferError == SD_OK)) {} if (TransferError != SD_OK) { return(TransferError); } } else if (DeviceMode == SD_DMA_MODE) { SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR, ENABLE); SDIO_DMACmd(ENABLE); SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, (NumberOfBlocks * BlockSize)); while ((SD_DMAEndOfTransferStatus() == RESET) && (TransferEnd == 0) && (TransferError == SD_OK)) {} if (TransferError != SD_OK) { return(TransferError); } } } /*!< Clear all the static flags */ SDIO_ClearFlag(SDIO_STATIC_FLAGS); /*!< Add some delay before checking the Card Status */ for(count = 0; count < 0x1FF; count++) { } /*!< Wait till the card is in programming state */ errorstatus = IsCardProgramming(&cardstate); while ((errorstatus == SD_OK) && ((cardstate == SD_CARD_PROGRAMMING) || (cardstate == SD_CARD_RECEIVING))) { errorstatus = IsCardProgramming(&cardstate); } return(errorstatus); } Вот тут почти в самом конце имеется задержка... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Allregia 9 12 сентября, 2012 Опубликовано 12 сентября, 2012 · Жалоба Хм..странно, в Вашей версии практически никакие проверки не делаются. У меня наверно постарей чутка версия: * @file stm32_eval_sdio_sd.c * @author MCD Application Team * @version V4.4.0 * @date 31-December-2010 Вы видимо не заметили - у меня и процессор чуть другой (F4 а не F1) * @file stm324xg_eval_sdio_sd.c * @author MCD Application Team * @version V1.0.2 * @date 09-March-2012 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 12 сентября, 2012 Опубликовано 12 сентября, 2012 · Жалоба Вы видимо не заметили - у меня и процессор чуть другой (F4 а не F1) Задержка насколько я понимаю касается алгоритма работы с SD картой, а не конкретного процессора. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Allregia 9 12 сентября, 2012 Опубликовано 12 сентября, 2012 · Жалоба Задержка насколько я понимаю касается алгоритма работы с SD картой, а не конкретного процессора. Так у него же и библиотеки другие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 13 сентября, 2012 Опубликовано 13 сентября, 2012 · Жалоба Кстати, а ктонибудь пробовал функцию удаления файла из Чановской FatFs? У меня она почемуто зависает напрочь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
spectral1989 0 14 сентября, 2012 Опубликовано 14 сентября, 2012 · Жалоба Итак, собрал проект на stm32f103 в котором есть USB mass storage, SD карта на 2гб и файловая система Chan'a FatFs. Все это работает через SDIO в поблочном режиме через DMA. Идея такая: ПК определяет флешку как mass storage device и если нужно скачивает с нее файлы логов работы устройств, подключенных к контроллеру по сети CAN(CAN не подключал пока к этому проекту, на stm32f103 can+usb вместе не работают). На контроллере стоит FatFs и заполняет эти самые файлы логов. По отдельности FatFs и USB mass storage работают нормально. Файлы пишутся/читаются/создаются, ПК определяет SD карту как флешку. Пробую объединить в один проект USB и FatFs и при попытке дописать что-нибудь в файл на SD карте контроллер вылетает в Hard Fault. Может тут есть какие-нибудь нюансы? Такую модель вообще можно реализовать? Кстати, а ктонибудь пробовал функцию удаления файла из Чановской FatFs? У меня она почемуто зависает напрочь у меня отлично работает. FatFs 9a, поблочная запись/чтение через DMA Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Allregia 9 14 сентября, 2012 Опубликовано 14 сентября, 2012 · Жалоба Кстати, а ктонибудь пробовал функцию удаления файла из Чановской FatFs? У меня она почемуто зависает напрочь Удаление отлично работает, проблем не видел. Вот где наткнулся - на форматировании, если форматировать подряд несколько разных флешек, на какой-то подвисает DMA. Столкнулся только на днях, и пока не придумал в чем дело. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 16 сентября, 2012 Опубликовано 16 сентября, 2012 · Жалоба По отдельности FatFs и USB mass storage работают нормально. Файлы пишутся/читаются/создаются, ПК определяет SD карту как флешку. Пробую объединить в один проект USB и FatFs и при попытке дописать что-нибудь в файл на SD карте контроллер вылетает в Hard Fault. Может тут есть какие-нибудь нюансы? Такую модель вообще можно реализовать? у меня usb и fatfs в одном проекте работают, только mass storage инициализируется после закрытия диска на fatfs. У Вас не так? Там запросы от USB разбираются в прерывании, так что в тот момент когда Вы пишете в файл вполне может произойти обращение к карте через эти же функции в прерывании. Надо запрещать прерывания на время пока пишете в файл. Видимо так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
spectral1989 0 17 сентября, 2012 Опубликовано 17 сентября, 2012 · Жалоба у меня usb и fatfs в одном проекте работают, только mass storage инициализируется после закрытия диска на fatfs. У Вас не так? Там запросы от USB разбираются в прерывании, так что в тот момент когда Вы пишете в файл вполне может произойти обращение к карте через эти же функции в прерывании. Надо запрещать прерывания на время пока пишете в файл. Видимо так. У меня наоборот, сначала инициализируется mass storage, потом только монтируется fatfs. как мне выгрузить mass storage? перепробовал разные варианты, сейчас делаю так: Bot_Abort(BOTH_DIR); Suspend(); PowerOff(); GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN); NVIC->ICER[0] |= (1 << (USB_HP_CAN1_TX_IRQn & 0x1F)); NVIC->ICER[0] |= (1 << (USB_LP_CAN1_RX0_IRQn & 0x1F)); при попытке записать что-нибудь в файл с помощью fatfs все равно вылетаю в hard fault Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 17 сентября, 2012 Опубликовано 17 сентября, 2012 · Жалоба У меня наоборот, сначала инициализируется mass storage, потом только монтируется fatfs. как мне выгрузить mass storage? при попытке записать что-нибудь в файл с помощью fatfs все равно вылетаю в hard fault Че гадать -посмотрите в стеке какая последняя функция вызвала аборт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться