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

ProductManualSDCardv2.2final.pdf

 

Раздел 5.5 Data Write.

Рисунок 5-5 Multiple Block Write Operation

На блок-схеме видно, что после CMD25 между любым блоком данных возможно появление BUSY.

 

По поводу грануляции SD-карт есть некоторое пояснение у Чена h__p://elm-chan.org/docs/mmc/mmc_e.html

 

Разве никто не делал лог появлений BUSY в мультисекторной записи? У меня на 8-гиговой возникали паузы после первого переданного блока данных в команде CMD25 и чтобы отправить остальные блоки приходится ждать пропадения BUSY. Причём грануляция появления BUSY в переводе на килобайты - от 16 КБ в начале файла коротких BUSY, и далее через грубо 8 раз грануляция увеличивается до 640 КБ и 45 мс BUSY. Карта по какой-то своей логике её меняет. Но блок, после которого формируется длинный BUSY сохраняется - после первого (видимо зависит от форматирования // кластерного сдвига // адреса в команде CMD25). В тесте CMD25 всегда была на 16 блоков.

 

 

Но я может быть перемудрил/преувеличил опасения по поводу "невыравненной мультиблоковой записи". Т.к. если в документе ProductManualSDCardv2.2final.pdf нет ограничений на выравнивание адреса, то видимо во всех SD-картах это изначально допускалось. И влияет невыровненность адреса (блока) только на момент формирования длинного BUSY.

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


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

Но я может быть перемудрил/преувеличил опасения по поводу "невыравненной мультиблоковой записи". Т.к. если в документе ProductManualSDCardv2.2final.pdf нет ограничений на выравнивание адреса, то видимо во всех SD-картах это изначально допускалось. И влияет невыровненность адреса (блока) только на момент формирования длинного BUSY.

Ограничений нет (и не было). Влияет, но для каждого типа карты влияние индивидуально, так что в конечном счете это не важно.

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


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

Что касаемо невыровненной записи, то за неё отвечают флаги WRITE_BLK_MISALIGN и WRITE_BL_PARTIAL в CSD.

Первый - определяет, допускает ли карта невыровненный начальный адрес блока, второй - допускает ли карта размер блока меньше чем 512.

Насколько я понял, первый роялит только для не-SDHC карт. (Потому что для SDHC карт не получится передать невыровненный адрес).

 

Что же до флага BUSY при мультиблоковой записи - не разу его не проверял, и не имел проблем. Возможно, с ним работает аппаратура SDIO контроллера.

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


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

Насколько я понял, первый роялит только для не-SDHC карт. (Потому что для SDHC карт не получится передать невыровненный адрес).

Да, в HC это убрали, но и на обычных картах никто (или почти никто) такую запись не поддерживал.

 

Что же до флага BUSY при мультиблоковой записи - не разу его не проверял, и не имел проблем. Возможно, с ним работает аппаратура SDIO контроллера.

BUSY, естественно, выставляется - иначе у карты не было бы возможности "притормозить" запись.

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


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

Если у кого есть информация, то любопытна и вторая вещь, о которой я писал. В SDHC BUSY может не вырабатываться после завершения мультисекторной записи. То есть карта накапливает непрерывные цепочки. Интересно, как давно и в каких типах такое стало происходить. И в связи с оптимизацией работы ПО с мультисекторной записью SD карт.

 

PS

Мой термин "невыравненная запись" отличался от документации SD-карт. Невыравненым считался адрес 512-байтного блока (не байта!) относительно грануляции NAND-памяти карты.

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

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


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

Пытаю SDIO на плате SK-STM32F217. Карту пока не подключал, хочу увидеть хоть какую-нибудь осмысленную активность на сигнальных линиях.

Осуществляю инициализацию и отправку команды, но вижу только мусор на линии CLK, на остальных ничего нет.

Может кто-нибудь проверить у себя мой вариант? Или подкинуть 100% рабочий код, без лишних функций.

 

static SDIO_InitTypeDef s_sdio_param = {
                                         SDIO_ClockEdge_Rising,
                                         SDIO_ClockBypass_Enable,
                                         SDIO_ClockPowerSave_Disable,
                                         SDIO_BusWide_1b,
                                         SDIO_HardwareFlowControl_Disable,
                                         0
                                       };

void bsp_sd_init (void)
{
    SDIO_CmdInitTypeDef SDIO_CmdInitStruct;


    s_gpio_init();

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE);

    SDIO_SetPowerState(SDIO_PowerState_ON);
    while (SDIO_GetPowerState() != 0x03)
    {
        continue;
    }

    SDIO_Init(&s_sdio_param);

    SDIO_ClockCmd(ENABLE);

    SDIO_CmdInitStruct.SDIO_CmdIndex = 0xAA;
    SDIO_CmdInitStruct.SDIO_Argument = 0xCCCCCCCC;
    SDIO_CmdInitStruct.SDIO_Response = SDIO_Response_No;
    SDIO_CmdInitStruct.SDIO_CPSM     = ENABLE;
    SDIO_CmdInitStruct.SDIO_Wait     = SDIO_Wait_No;
    SDIO_SendCommand(&SDIO_CmdInitStruct);
}

static void s_gpio_init (void)
{
    GPIO_InitTypeDef GPIO_InitStructure;


    RCC_AHB1PeriphClockCmd(RCC_CLK |
                           RCC_CMD |
                           RCC_D3  |
                           RCC_D2  |
                           RCC_D1  |
                           RCC_D0, ENABLE);

    GPIO_PinAFConfig(GPIO_CLK, PINSOURCE_CLK, GPIO_AF_SDIO);
    GPIO_PinAFConfig(GPIO_CMD, PINSOURCE_CMD, GPIO_AF_SDIO);
    GPIO_PinAFConfig(GPIO_D3,  PINSOURCE_D3,  GPIO_AF_SDIO);
    GPIO_PinAFConfig(GPIO_D2,  PINSOURCE_D2,  GPIO_AF_SDIO);
    GPIO_PinAFConfig(GPIO_D1,  PINSOURCE_D1,  GPIO_AF_SDIO);
    GPIO_PinAFConfig(GPIO_D0,  PINSOURCE_D0,  GPIO_AF_SDIO);

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

    GPIO_InitStructure.GPIO_Pin = PIN_CMD;
    GPIO_Init(GPIO_CMD, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = PIN_D3;
    GPIO_Init(GPIO_D3,  &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = PIN_D2;
    GPIO_Init(GPIO_D2,  &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = PIN_D1;
    GPIO_Init(GPIO_D1,  &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = PIN_D0;
    GPIO_Init(GPIO_D0,  &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Pin  = PIN_CLK;
    GPIO_Init(GPIO_CLK, &GPIO_InitStructure);
}

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

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


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

Вопрос знатокам SDIO.(Завершаю мост на FPGA SDIO<-> N*UART)

 

Если по линии CMD кадр начинается с нулевого бита, то как обнаружить начало информационного кадра по DATA[3:0]? Я стал сомневаться, что для SD на входе CLK может отсутствовать частота (А значит именно её появление начинает отсчет информации).

Что наблюдали осциллографом? В Интернете противоречивая информация...

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


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

В Интернете противоречивая информация...

Судя по всему, начинается с "0".

post-27702-1517342507_thumb.png

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


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

Судя по всему, начинается с "0".

Это ценно. Огромное ВАМ спасибо!!!

 

...остается выяснить CRC вычисляется с учетом этого стартового нуля или ТОЛЬКО данные в учете?

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


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

...остается выяснить CRC вычисляется с учетом этого стартового нуля или ТОЛЬКО данные в учете?

Только данные, по каждой линии отдельно.

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


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

Это ценно. Огромное ВАМ спасибо!!!

 

...остается выяснить CRC вычисляется с учетом этого стартового нуля или ТОЛЬКО данные в учете?

Рекомендую ознакомиться с SD Specifications Part 1 Physical Layer Simplified Specification Version 3.01:

When the wide bus option is used, the data is transferred 4 bits at a time (refer to Figure 3-7). Start and

end bits, as well as the CRC bits, are transmitted for every one of the DAT lines. CRC bits are

calculated and checked for every DAT line individually. The CRC status response and Busy indication

will be sent by the card to the host on DAT0 only (DAT1-DAT3 during that period are don't care).

Более подробно про разные CRC описано в разделе 4.5 Cyclic Redundancy Code (CRC).

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


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

Только данные, по каждой линии отдельно.

Странная фантазия... 4 вычислителя?... Трудно такую мысль представить у задумщиков SDIO

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


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

Странная фантазия... 4 вычислителя?... Трудно такую мысль представить у задумщиков SDIO

Странно было бы сделать иначе.

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


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

Странно было бы сделать иначе.

Хм....

Проще гонять в сдвиговом регистре полином сразу по 4м линиям, чем 4мя по каждой из линий...

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


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

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

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

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

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

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

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

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

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

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