|
stm32f10x, FatFs + SDIO + SD card + USB, mass storage device |
|
|
|
Sep 5 2012, 09:51
|
Частый гость
 
Группа: Свой
Сообщений: 76
Регистрация: 5-04-12
Из: Томск
Пользователь №: 71 210

|
Здравствуйте! Имеется в наличии отладочная плата от терра электроники на stm32f103, пробую запустить SDIO + SD card + USB. Cкачал с сайта СТ либу usb mass storage device на stm32f10x, поправил под свою плату, запустил, но все работает не совсем так, как хотелось бы. Инициализация карты проходит. В системе появляется съемный диск, размер 0 байт, файловая система RAW, хотя я ее форматировал через FatFs в fat32, размер сектора = 512. При попытке открыть предлагает отформатировать, нажимаю да - появляется окошко, там указан размер карты 3,75гб, стало быть до карты проц достучаться может. Пробую форматировать - вылезает ошибка, не удается завершить форматирование. В чем может быть проблема?
Пробовал уменьшать частоту тактирования карты: увеличил делитель с 1 до 0хА - не помогает.
И еще вопрос, я скачал библиотеку FatFs и прикрутил к ней низкоуровневые функции stm32f10x - заработало, читает и пишет, создает файлы и форматирует. Теперь, чтобы при соединении через USB с компьютером я мог работать на нем с SD картой мне нужно сделать примерно так:
SD карта -> интерфейс обмена данными(SDIO в моем случае) -> драйвер файловой системы(FatFs в моем случае) -> драйвер USB mass storage device -> ПК я правильно понимаю ситуацию?
Сообщение отредактировал spectral1989 - Sep 5 2012, 11:03
|
|
|
|
|
 |
Ответов
|
Sep 7 2012, 07:30
|
Частый гость
 
Группа: Свой
Сообщений: 76
Регистрация: 5-04-12
Из: Томск
Пользователь №: 71 210

|
Заметил такой глюк: беру архив около 100мб, копирую на SD карту, проверяю контрольные суммы - сходится. Копирую архив с карты на ПК, проверяю контрольные суммы - опять сходится. Делаю безопасное извлечение, вытаскиваю шнур USB, вставляю - карта определяется корректно(правильный размер, есть файл, который я создал с помощью FatFs), но этого архива нет. В чем проблема может быть? Alexashka, пожалуйста скиньте все таки свой проект  з.ы. мультиблок с ходу не заработал, я его пока отложил
Сообщение отредактировал spectral1989 - Sep 7 2012, 07:35
|
|
|
|
|
Sep 7 2012, 17:05
|

Практикующий маг
     
Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576

|
Цитата(spectral1989 @ Sep 7 2012, 11:30)  Заметил такой глюк: беру архив около 100мб, копирую на SD карту, проверяю контрольные суммы - сходится. Копирую архив с карты на ПК, проверяю контрольные суммы - опять сходится. Делаю безопасное извлечение, вытаскиваю шнур USB, вставляю - карта определяется корректно(правильный размер, есть файл, который я создал с помощью FatFs), но этого архива нет. В чем проблема может быть? Alexashka, пожалуйста скиньте все таки свой проект  з.ы. мультиблок с ходу не заработал, я его пока отложил Хм...интересный эффект, как будто данные о созданном файле были занесены в кэш но не прописались в ФАТ таблицу на диске. Попробуйте проделать тоже самое с картой вставив ее в какойнить картридер -может карта глючная. У меня есть карточка (недавно купленная) с которой я не могу удалить файлы, и не могу отформатировать ее. Т.е файлы удаляются, потом вытащишь-вставишь -а они тут как тут, все на месте Я писал много раз уже, но мелкие файлы, пропадания не замечено. Надо будет попробовать записать большой. Карты у меня на 1,2,4,8 ГБ. Проблем не было никаких. Которая за 4 сек открывается это 4ГБ, класс 10, Трансценд вроде бы. Сейчас ничего не могу скинуть, проект на работе, так что -до понедельника  Есть еще на 2Гб, помню она дольше открывается и пишется, раза в 2 точно если не в 3. Заметил еще такую вещь -если на карте есть мультимедийные файлы то открывание диска затягивается на очень длительное время... ЗЫ. Кстати, а сколько у Вас пишется по времени 100МБ?
|
|
|
|
|
Sep 8 2012, 21:17
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(Alexashka @ Sep 7 2012, 19:05)  Есть еще на 2Гб, помню она дольше открывается и пишется, раза в 2 точно если не в 3. Попробуте форматнуть ее прямо в устройстве, командой f_mkfs - у меня это увеличило скорость записи почти на порядок! Правда немного другой процессор. Обсуждалось тут: http://electronix.ru/forum/index.php?showtopic=105763
|
|
|
|
|
Sep 11 2012, 08:08
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(Alexashka @ Sep 10 2012, 18:43)  Похоже у Вас не работает как положено мультиблоковая запись. Если используете драйвер 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); }
|
|
|
|
|
Sep 12 2012, 04:42
|

Практикующий маг
     
Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576

|
Цитата(Allregia @ Sep 11 2012, 12:08)  Да, его. Не пойму где именно надо покоцать. Вот процедура блочной записи: Хм..странно, в Вашей версии практически никакие проверки не делаются. У меня наверно постарей чутка версия: Код * @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); } Вот тут почти в самом конце имеется задержка...
|
|
|
|
|
Sep 12 2012, 07:46
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(Alexashka @ Sep 12 2012, 06:42)  Хм..странно, в Вашей версии практически никакие проверки не делаются. У меня наверно постарей чутка версия: Код * @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
|
|
|
|
Сообщений в этой теме
spectral1989 stm32f10x, FatFs + SDIO + SD card + USB Sep 5 2012, 09:51 Alexashka проверьте питание на карте памяти -должно быть 3.3... Sep 5 2012, 19:33 spectral1989 С транзистором я разобрался еще когда FatFs ковыря... Sep 6 2012, 02:12 spectral1989 Проверил на всякий случай питание, все ок! 3,3... Sep 6 2012, 03:57 Alexashka Цитата(spectral1989 @ Sep 6 2012, 07:57) ... Sep 6 2012, 08:18 spectral1989 флаг CMDREND - command responce recieved(CRC check... Sep 6 2012, 09:20 spectral1989 включил hardware flow control и заработало ПК дума... Sep 6 2012, 10:26 Alexashka Цитата(spectral1989 @ Sep 6 2012, 14:26) ... Sep 6 2012, 11:20 spectral1989 3-4с время открытия? а какого объема карту подключ... Sep 7 2012, 02:56       Alexashka Цитата(Allregia @ Sep 12 2012, 11:46) Вы ... Sep 12 2012, 07:59        Allregia Цитата(Alexashka @ Sep 12 2012, 09:59) За... Sep 12 2012, 12:42 spectral1989 купил несколько новых карт: 2, 4, 8гб разного клас... Sep 10 2012, 05:11 spectral1989 собрал заново проект, все заработало. видимо накос... Sep 10 2012, 10:49 Alexashka Кстати, а ктонибудь пробовал функцию удаления файл... Sep 13 2012, 08:59 spectral1989 Итак, собрал проект на stm32f103 в котором есть US... Sep 14 2012, 03:42  Alexashka Цитата(spectral1989 @ Sep 14 2012, 07:42)... Sep 16 2012, 17:33   spectral1989 Цитата(Alexashka @ Sep 16 2012, 21:33) у ... Sep 17 2012, 04:51    Alexashka Цитата(spectral1989 @ Sep 17 2012, 08:51)... Sep 17 2012, 16:29 Allregia Цитата(Alexashka @ Sep 13 2012, 10:59) Кс... Sep 14 2012, 11:04
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|