Ну мы, эмбеддеры, люди привыкшие, что все надо инициализировать, поэтому SD карта не является исключением из этого великолепнейшего правила. Нужно прочекать поддерживаемые напряжения, назначить адреса, и вообще, убедиться, что мы можем работать с данной картой. Посмотрим на алгоритм инициализации, вытащенный из спецификаии и пройдемся по нему по порядку, блок за блоком, дабы понять, что нужно сделать с девайсом перед использованием по назначению.
ВАЖНО: инициализация проводится на низко скоростном режиме! Частота клока карты не более 400 кГц!!!
ЕЩЕ ВАЖНО: после подачи питания, не спешим грузить карту командами, дадим напряжению устаканиться, подождем 250 миллисекунд (можно чуть подольше, в зависимости от числа карт, подключенных к одной шине, ширины линии данных и параметров источник питания). Как только вольтаж вышел на необходимый уровень, зарядились все паразитные емкости и т.д. и т.п., можно творить процесс инициализации. А начинается он с обнуления всех карт и перевода их в Idle State.
• Шлем CMD0, обратим внимание, без аргумента и не ждем ничего в отклике. В результате все карты на линии передут в холостой режим.
• Помните, я говорил, что напряжение нужно валидировать? Правильно! Нужно сказать карте, на каком вольтаже мы работаем и выслушать от нее все по этому поводу. Шлем CMD8 с аргументом, в котором биты 11:8 означают напряжение хоста и биты 7:0 – check pattern (проверочный шаблон) – любой, спецификация рекомендует слать 10101010. Биты напряжения ставятся в соответствии с таблицей:
Ну, у нас все очень даже определено и далеко не Low Voltage Range. Stm32f4 выдает как раз напряжение в диапазоне 2.7 – 3.6 V, так что ставим 1 на восьмом бите аргумента. Итого, имеем команду с аргументом 110101010. Отправили. Прочекали, что все отправилось хорошо и ждем ответа, он не заставит нас делать это долго. В спецификации увидели, что ответ на эту команду – R7 типа.
Если мы его так и не дождались, то дальнейшая команда ACMD41 решит, как именно нас надули – подсунули карту версии 1.X стандартной емкости или вообще не SD карту. Правда есть вероятность, что мы просто что-то не так делаем. Но не будем о грустном, и предположим, что флешка все таки ответила. Если с напряжением все хорошо, карта довольна, мы довольны, ответ будет содержать в себе все то, что мы отправили в аргументе, то есть 110101010. Это называется valid esponse. Если так, переходим к дальнейшему шагу, иначе – опять же – либо надули, либо где-то косяк.
• Дождались 110101010, и пришло время непосредственной инициализации – команды ACMD41. И тут вспоминаем ВАЖНОСТЬ: чтобы сказать карточке, что команда не простая, а ACMD, отправим сперва CMD55. В аргументе обязательно указываем, адрес той карты, для которой эта команда предназначена. Но стоп, у нас, ведь, пока нет адреса, мы его не знаем. Ничего, узнаем … но по позже, а пока пишем нули и шлем. Получив ответ типа R1 удостоверяемся, что карта готова принимать ACMD и только после этого шлем 41 индекс! Команда идет с аргументом, в котором на месте 30-ого бита указываем 1, что говорит о поддерживаемости хостом SDHC карт и напряжения хоста на месте 23:0 битов (см. содержимое OCR регистра). Ответ ждем R3 типа. Здесь нам важно получить 1 на месте 31ого бита в пачке ответа, несущей содержимое OCR регистра карты (флаг busy). Это будет говорить о том, что карта завершила процесс инициализации. Виду того, что этот процесс длится долго (гораздо дольше, чем тактовый цикл микроконтроллера), необходимо слать ACMD41 в цикле до тех пор, пока не получим ответ со снятым флагом занятости. Как только это случилось, чекам 30 бит, и, если он единица, то имеем карту повышенной емкости SDHC или SDXC, и карту стандартной емкости SD в противном случае. Если же мы ждали, ждали, а флаг бизи все висит и висит, то, как и в описанном выше случае – либо неподходящая карта, либо (скорее всего) наш косяк.
• Далее шлем CMD2 — без аргумента и смотрим на ответ R2. В этом случае он будет нести информацию о содержимом CID регистра, и мы сможем вычитать ID производителя, серийный номер карты и прочую информацию.
• И, наконец, заключительный шаг – получение адреса карты (RCA — relative
address). Как оно уже упоминалось, к одной шине может быть подключено несколько карт, поэтому каждая должна иметь свой уникальный локальный адрес. Шлем CMD3 и получаем ответ типа R6, в котором в младших 16 битах содержится статус карты, а в старших – новый RCA адрес. Отныне, для доступа к нашей карточке, мы должны будем звать ее по имени, то есть по RCA адресу.
• Опциональный пункт. По умолчанию карта работает с 1-битной шиной данных, что, ясное дело, медленнее, чем с 4-х битной. Если мы хотим достичь максимального быстродействия – шлем ACMD6, с предшествующей CMD55, конечно же. Но прежде, нужно перевести карту в состояние Transfer State (см. ниже) командой CMD7 с RCA в качестве аргумента. В аргументе ACMD6 на месте самого первого бита пишем 1 – если хотим включить 4-битный мод и 0 – для отключение. Ответ R1 скажет об успешном проведении операции.