yanichar 0 7 февраля, 2012 Опубликовано 7 февраля, 2012 · Жалоба Камень STM32F205RET6. Как реализовать запись нескольких блоков(аналог SD_WriteMultiBlocks) на SD карту через интерфейс SDIO в режиме полинга? DMA неприемлемо, так как производительность DMA2 уже полностью исчерпана другими передачами. Заранее спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReRayne 0 7 февраля, 2012 Опубликовано 7 февраля, 2012 (изменено) · Жалоба В примере файловой системы FATFS для STM32 чтение и запись пуллингом выглядят следующим образом: /* read sectors */ for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++) { Status = SD_ReadBlock((buff+SECTOR_SIZE*secNum), (sector+secNum)*SECTOR_SIZE, SECTOR_SIZE); while(SD_GetStatus() != SD_TRANSFER_OK); } /* write sectors */ for (int secNum = 0; (secNum < count) && (Status == SD_OK); secNum++) { Status = SD_WriteBlock((uint8_t *) buff+SECTOR_SIZE*secNum, (sector+secNum)*SECTOR_SIZE, SECTOR_SIZE); while(SD_GetStatus() != SD_TRANSFER_OK); } Данные куски кода с библиотеке как раз заменяют MultiBlock при использовании DMA. Изменено 7 февраля, 2012 пользователем ReRayne Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanichar 0 7 февраля, 2012 Опубликовано 7 февраля, 2012 (изменено) · Жалоба Данные куски кода с библиотеке как раз заменяют MultiBlock при использовании DMA.Но при этом карта получает куски информации не как запись нескольких блоков, а как одиночные блоки, что сильно замедляет её работу. Вот функция, которая осуществляет запись по DMA 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; } /*!< 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); SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE); SDIO_DMACmd(ENABLE); SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, (NumberOfBlocks * BlockSize)); return(errorstatus); } Идея в том, чтобы выкинуть предпоследнюю строку(SD_LowLevel_DMA_TxConfig....) и вручную кидатся словами(или байтами) по мере их проглатывания интерфейсом Изменено 7 февраля, 2012 пользователем IgorKossak [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReRayne 0 7 февраля, 2012 Опубликовано 7 февраля, 2012 (изменено) · Жалоба Если честно, он и с DMA(у меня F217) не шибко быстро работает. Посмотрела как работает WriteBlock в пуллинге. В начале функции есть структура SDIO_CmdInitStructure, которая содержит в себе адрес записываемого блока. SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize) { /*****************************************************************/ SDIO_CmdInitStructure.SDIO_Argument = WriteAddr; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_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); /*****************************************************************/ /* Тут запись по uint32_t */ /*****************************************************************/ } Других вариантов, кроме как цикл, я не вижу, ибо структуру нужно регулярно переиницализировать, команды CmdResp1Error(SD_CMD_SET_BLOCK_COUNT) и errorstatus = CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK), используемые в DMA, вряд ли сработают. SD_Error SD_WriteBlockMultiPooling(uint8_t *writebuff, uint32_t uint16_t BlockSize, uint32_t NumberOfBlocks) { uint32_t i; /*****************************************************************/ for (i = 0; i < NumberOfBlocks; i++) { SDIO_CmdInitStructure.SDIO_Argument = WriteAddr + i; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_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); /*****************************************************************/ /* Тут запись по uint32_t */ } /*****************************************************************/ } Собственно, получается тоже самое, что я написала в первом посте, с разницей лишь в том, что тут не тратится время на повторный вызов WriteBlock. Изменено 7 февраля, 2012 пользователем ReRayne Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanichar 0 9 февраля, 2012 Опубликовано 9 февраля, 2012 · Жалоба Все равно получается что запись идет по одному блоку, это замедляет работу до неприемлемого уровня. Нужна обязательно мультиблоковая запись. Ещё идеи есть? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться