реклама на сайте
подробности

 
 
> SD_WriteMultiBlocks в поллинг режиме на STM32F205
Yanichar
сообщение Feb 7 2012, 18:57
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 20-06-10
Из: Украина, Харьков
Пользователь №: 58 028



Камень STM32F205RET6. Как реализовать запись нескольких блоков(аналог SD_WriteMultiBlocks) на SD карту через интерфейс SDIO в режиме полинга? DMA неприемлемо, так как производительность DMA2 уже полностью исчерпана другими передачами. Заранее спасибо.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 4)
ReRayne
сообщение Feb 7 2012, 19:06
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 25
Регистрация: 12-10-11
Из: Москва
Пользователь №: 67 699



В примере файловой системы 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 - Feb 7 2012, 19:07
Go to the top of the page
 
+Quote Post
Yanichar
сообщение Feb 7 2012, 19:17
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 20-06-10
Из: Украина, Харьков
Пользователь №: 58 028



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

Сообщение отредактировал IgorKossak - Feb 7 2012, 20:11
Причина редактирования: [codebox]
Go to the top of the page
 
+Quote Post
ReRayne
сообщение Feb 7 2012, 19:37
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 25
Регистрация: 12-10-11
Из: Москва
Пользователь №: 67 699



Если честно, он и с 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 - Feb 7 2012, 19:46
Go to the top of the page
 
+Quote Post
Yanichar
сообщение Feb 9 2012, 15:34
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 20-06-10
Из: Украина, Харьков
Пользователь №: 58 028



Все равно получается что запись идет по одному блоку, это замедляет работу до неприемлемого уровня. Нужна обязательно мультиблоковая запись. Ещё идеи есть?
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 1st August 2025 - 20:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01377 секунд с 7
ELECTRONIX ©2004-2016