Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SD_WriteMultiBlocks в поллинг режиме на STM32F205
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Yanichar
Камень STM32F205RET6. Как реализовать запись нескольких блоков(аналог SD_WriteMultiBlocks) на SD карту через интерфейс SDIO в режиме полинга? DMA неприемлемо, так как производительность DMA2 уже полностью исчерпана другими передачами. Заранее спасибо.
ReRayne
В примере файловой системы 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.
Yanichar
Цитата(ReRayne @ Feb 7 2012, 23:06) *
Данные куски кода с библиотеке как раз заменяют MultiBlock при использовании DMA.
Но при этом карта получает куски информации не как запись нескольких блоков, а как одиночные блоки, что сильно замедляет её работу.
Вот функция, которая осуществляет запись по DMA
CODE
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....) и вручную кидатся словами(или байтами) по мере их проглатывания интерфейсом
ReRayne
Если честно, он и с 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.
Yanichar
Все равно получается что запись идет по одному блоку, это замедляет работу до неприемлемого уровня. Нужна обязательно мультиблоковая запись. Ещё идеи есть?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.