Перейти к содержанию
    

SD_WriteMultiBlocks в поллинг режиме на STM32F205

Камень STM32F205RET6. Как реализовать запись нескольких блоков(аналог SD_WriteMultiBlocks) на SD карту через интерфейс SDIO в режиме полинга? DMA неприемлемо, так как производительность DMA2 уже полностью исчерпана другими передачами. Заранее спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В примере файловой системы 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.

Изменено пользователем ReRayne

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Данные куски кода с библиотеке как раз заменяют 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....) и вручную кидатся словами(или байтами) по мере их проглатывания интерфейсом

Изменено пользователем IgorKossak
[codebox]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если честно, он и с 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.

Изменено пользователем ReRayne

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все равно получается что запись идет по одному блоку, это замедляет работу до неприемлемого уровня. Нужна обязательно мультиблоковая запись. Ещё идеи есть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...