Распиновка слота карты памяти

Обновлено: 03.07.2024

Как-то давно хотел себе сделать логгер температуры, возникла необходимость использовать внешнюю EEPROM память. Прикинув, что в наличие имеется 512кб память с i2c интерфейсом, сделал на ней экспериментальный логгер. Но когда возникла необходимость скинуть данные на компьютер для последующей обработки, то вылезли трудности с написанием софтины, которая бы считывала данные с EEPROM и писала бы их в текстовый файл.

Софтину я написал, только работала она как-то корявенько и медленно, для меня сойдет, а вот для массового производства корявости недопустимы. Захотелось писать данные на карту памяти, которую можно потом вставить в карт-ридер и через проводник перекинуть на компьютер, где их уже можно обрабатывать чем удобно. Для этого нужно уметь собственно писать данные на карту памяти, и знать файловую систему FAT, чтобы карточка распозналась компьютером. С этого вступления хочу начать небольшой цикл из 3-х статей, в котором я напишу про то, как работать с SD/MMC картой памяти и файловой системой FAT.
Карточку SD я выбрал из-за того, что внутри ее есть встроенный контроллер и что с ней можно работать в SPI 0 режиме (положительный синхроимпульс, защёлкивание по переднему фронту, сдвиг по заднему фронту), с которым довольно просто совладать. Посмотрим на распиновку(цоколевку) SD карты:

Видно, что карточка имеет 9 контактов, предназначение их следующее.

При работе с микроконтроллерами режима SPI за глаз хватает по скорости, потому использовать родной режим работы карты памяти будет нецелесообразно. Нам понадобятся пины DI, DO, CLK, CS для передачи данных и VSS, VDD для питания. Теперь немного про питание, SD карта требует от 2,7В до 3,6В, и тока до 100мА. Также если планируется горячее подключения, нужно предусмотреть просадку питающего напряжения при подсоединении карты. Иначе питание может просесть до такого уровня, когда BOD детектор сработает и ресетнет микроконтроллер. Этого можно избежать, налепив по питания конденсаторов и индуктивность. Учитывая все это, была слеплена стендовая платка для работы с SD картой:

Схема платки показана ниже:

Для питания карты памяти предусмотрен стабилизатор на 3,3В - LP2980-3.3. Его обвязка из конденсаторов C1,C3 – 100мкф, танталовые; C2,C4 – 0,1мкф, керамика; L1 – индуктивность на 22мкГн. Для сопряжения TTL уровней сигналов предусмотрены резистивные делители R2-R4 по 5,6кОм; R5-R7 по 10кОм. Светодиод D1 – сигнальный, для него ограничивающий резистор R1 – 470 Ом. Также на разъеме оказались выводы WP и INS, отслеживая состояния которых можно понять, защищена ли карта от записи механической защелкой, и присутствует ли карта в разъеме соответственно. Далее дело за подключением, все сигналы с карты подключил к PortB микроконтроллера. Нежелание использовать аппаратный SPI микроконтроллера буду аргументировать плохой переносимостью кода на разные модели микроконтроллеров. Для работы с SD картой сразу буду использовать ATmega32 (при работе с FAT нам понадобится около 20кб флеша). Хотя можно использовать хоть Atmega8, благо код для этого переделывать не нужно. Схема подключения к микроконтроллеру показана ниже:

Тактовый генератор – встроенный RC на 8Мгц, хотя можно использовать любой, но с 8Мгц работает шустро. Конденсаторы C5,C7 – по 100мкФ, электролиты, С4,С6 – 0,1мкф, керамика. Так как мы будем передавать большие объемы данных (стандартный блок – 512 байт), то выводить их будем по UART на компьютер в программу Terminal 1.9. Про сопряжение UART микроконтроллера с компьютером я писал уже неоднократно вот здесь, здесь и даже здесь.

Теперь у нас есть все железо для экспериментов с картой памяти. Но прежде чем перейти к программной части, упомянем, что карта типа MMC также может работать в SPI режиме. Для ее управления также стоит использовать выводы DI, DO, CLK, CS. Схемотехнические рассуждения для MMC такие же, как и для SD карты. Распиновка MMC карты показана ниже:

Перейдем к программной части. Рассмотрим, как инициализировать карту, и писать/читать из нее. Для перехода в режим SPI нужно дождаться, пока питающее напряжения на карте достигнет 3В (несколько миллисекунд, после включения) и подать более 74 импульса на выводе CLK, при высоком уровне на CS и DI выводах.

После нужно выставить на CS нулевой уровень, далее карта входит в режим SPI, теперь для успешной работы следует подать команды сброса и инициализации CMD0, CMD1 прежде, чем мы сможем писать/читать данные из карты. Команд для карты довольно много, часть из них приведена в таблице ниже:

Команд много, но основанная масса работы производится командами CMD0, CMD1 (сброс и инициализация) CMD17 (чтение), CMD24 (запись). Весь перечень команд и как с ними работать, можно просмотреть в родной спецификации SD карты на английском.
Рассмотрим формат команды для SD карты.

Сперва идет индекс команды. Индекс команды в десятичном виде определяется как 64+имя команды. Далее следует 4 байта аргументов (данные, адрес), после следует 7-ми битная контрольная сумма. После успешной отправки команды следует послать байтовую паузу из 8*N тактовых импульсов (N - целое), после чего карта ответит. Ответ может быть типа R1,R2,R3. В нашем случае, ответы будут только типа R1. Поэтому рассмотрим только его.

Старший бит R1 всегда равен 0. Назначения остальных битов хорошо видно с рисунка.
Рассмотрим процесс инициализации карты памяти командами CMD0,CMD1. Сперва, при высоком уровне на выводах CS и DI подаем 80 тактовых импульсов на вывод CLK. Далее на все время работы с картой сажаем CS на землю, подаем команду CMD0, контрольная сумма для которой равнa 0x95 (контрольная сумма в нашем случае нужна только для команды CMD0, в остальных случаях она не проверяется, поэтому все время будем использовать 0х95 как контрольную сумму). Далее, после байтовой паузы, карточка должна ответить 0х01, что означает, что она вошла в SPI режим и готова принимать команды. Теперь подаем команды CMD1, и после паузы ожидаем от карточки ответа 0х00, которые говорит о том, что карта готова к обмену данными.

Обмен данными между картой памяти и микроконтроллером будет производиться стандартными блоками по 512 байт. Адресация карты побайтная, начиная с нуля, но считывать данные можно только блоками. Адресом блока служит первый его байт. То есть 0-й блок имеет адрес 0х0000, 1-й блок - 0х0200, 2-й блок – 0х400 и т.д. (справедливо для размера блока 512 байт). В SDHC картах адресация поблочная, адресом блока служит его номер. Операция чтения блока производится в следующем порядке. Подается команда CMD17, байтовая пауза, если принимается ответ 0х00, то после еще одной байтовой паузы принимается блок данных, структура которого показана ниже.

Некое подобие временной диаграммы операции чтения можно посмотреть на рисунке ниже

Как видно, блок начинается с байта 0хFE (для команд CMD17/18, CMD24), далее идет 512 байт информации и 2 байта контрольной суммы (которая по умолчанию не используется). Операция записи производиться похоже, команда CMD24, пауза, ответ карты 0х00, и блок данных (так как контрольная сумма не проверяется, то ее поле можно заполнить случайно ). Далее следует ответ карты про прием блока данных.

После чего busy состояние, когда карта записывает полученные данные. Временная диаграмма операции записи приведена ниже.

Для подтверждения вышесказанного хочу привести пример работы с картой. Запишем в блок под номером 1 (адрес 0х0200) какие-то циклически повторяющиеся данные, например чередующиеся цифры от 0 до 9, а потом считаем этот же блок и посмотрим, записались ли наши данные. Для этого была написана небольшая программка :


Код программы прост, название функций говорит само за себя. Вначале инициализируем UART, посредством которого будем связываться с компьютером на скорости 256кбод/с, с одним стоп битом, без проверки четности (если такая скорость покажется большой по ряду причин, то ее легко подредактировать в строке 16). Функция void uart_init(void) инициализирует UART; void uart_transmit(unsigned char х) – пересылает байт х по UART; unsigned char uart_receive(void) – принимает байт; void uart_transmit_message(char * msg) – пересылает строку, на которую ссылается msg по UART. Подключение карты к микроконтроллера определяется директивами define в начале программы. Рассмотрим функции работы c картой SD/MMC. Функции void spi_transmit(unsigned char x), unsigned char spi_receive(void) отвечают за пересылку байт по SPI; unsigned char sd_cmd(unsigned char b0, unsigned char b1, unsigned char b2, unsigned char b3, unsigned char b4, unsigned char b5) – отвечает за пересылку команды карте памяти.

b0 – индекс команды, b1-b4 – аргумент команды, b5 – контрольная сумма, функция возвращает ответ R1 от карточки. Пользовательские функции: unsigned char sd_card_init(void) служит для инициализации карты командами CMD0, CMD1, при успешном выполнении возвращает результат 0х00. Функции unsigned char read_block (char* buff, unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4) и unsigned char write_block (char* buff, unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4) служат для чтения/записи блока, на который указывает buff, по адресу a1-a4, в случае выполнения возвращают 0х00. Во всех пользовательских функция предусмотрена проверка наличия карты в слоте и режима Write Protect, который устанавливается механическим ползунком на самой карте памяти.

При внутрисхемном программировании следует вынимать карту из слота, иначе программатор не сможет залить прошивку в микроконтроллер (сигналы WP, INS при вставленной карте садят на землю выводы нужные для внутрисхемного программирования). Выполнение приведенной выше программы приведет к тому, что целостность файловой системы (существовавшей до этого на карточке) будет нарушена, так что перед экспериментами не забудьте скопировать с карточки всю важную информацию.
Вот что я увидел в Terminal 1.9 при запуске программы:

Решил перепроверить с помощью утилиты WinHex содержание первого блока карты памяти:

Результаты совпадают. Запись чтение удалось. Теперь смело можно писать/читать данные на карту. Про то, как писать данные в файлы и про файловую систему FAT я напишу чуть позже.

Учимся работать с SDHC/SDXC-картами по протоколу SPI

Немного матчасти

«SD» расшифровывается как «Secure Digital». Причем тут безопасность не знает никто. Внутри SD-карты находится обычная flash-память и микроконтроллер, осуществляющий общение с внешним миром. То есть, в первом приближении, это точно такая же non-volatile память, как и SPI flash.

SD-карты бывают трех типов. Карты SDSC (SC = Standard Capacity) позволяют хранить до 2 Гб информации и используют файловую систему FAT12 или FAT16. Эти карты морально устарели, в магазинах их найти непросто, да и по цене они сопоставимы с картами большего объема. Кроме того, они используют протокол, несколько отличающийся от протокола SDHC/SDXC-карт. В силу названных причин, с этого момента про существование SDSC мы забудем. К современным типам карт относятся SDHC (HC = High Capacity), использующие файловую систему FAT32 и способные хранить до 32 Гб данных, а также SDXC (XC = eXtended capacity), использующие exFAT и имеющие объем до 2 Тб. С точки зрения протокола эти карты неотличимы. Разница заключается только в файловой системе, выбор которой диктуется спецификацией.

Разумеется, ничто не мешает отформатировать SDHC карту под exFAT, или SDXC карту под какой-нибудь ZFS. Но ваш смартфон или фотоаппарат, вероятно, не сможет работать с такой картой.

Fun fact! Встречаются поддельные SDHC карты, которые на самом деле являются SDSC. В обычном магазине вы такие, скорее всего, не найдете, а вот на eBay налететь можно. Если вам предлагают купить типа SDHC карту объемом всего лишь 1 Гб, она наверняка на самом деле является SDSC.

На следующем фото изображена моя небольшая коллекция SD и MicroSD-карт, а также модулей для подключения их к отладочным платам (Arduino, Nucleo и подобным):

SD-карты и модули для работы с ними

Подключение SD-карты

Ниже изображена распиновка SD и MicroSD-карт:

Расположение пинов на SD и MicroSD-картах

  • Ни в коем случае не подавайте 5 В на пин VDD! Все SD-карты гарантировано работают от 3.3 В. Некоторые при этом также могут работать и от 5 В, но это не гарантируется. Если подать 5 В, вы рискуете спалить вашу дорогую карточку на 128 Гб, после чего ее останется только выкинуть;
  • По тем же соображениям, если ваш проект использует пятивольтовую логику, крайне рекомендуется использовать конвертер уровней, например TXS0108E (даташит [PDF]);
  • Платы Arduino имеют пин 3V3, но не могут подавать на него большой ток. Если запитать SD-карту от этого пина, можно словить забавные глюки. Например, карта будет нормально работать в одиночестве, но переставать работать при подключении к плате TFT-экранчика на базе ST7735, чья подсветка также питается от 3V3. Поэтому, если вы проектируете модуль или Arduino-шилд, используйте понижающий стабилизатор напряжения на 3.3 В вроде AMS1117 ;
  • Пин DO (он же MISO) должен быть обязательно подтянут к плюсу через резистор на 10 кОм или около того. Некоторые карты просто не будут стартовать без этого резистора. Например, я наблюдал такое поведение на картах производства Sony;

Теперь становится понятно, почему простые модули, имеющие только слот для подключения карты, не очень подходят. Также теперь ясно, как сделать модуль для подключения MicroSD-карт из адаптера. Отмечу, что пины с землей (VSS1 и VSS2) в адаптере, как правило, уже соединены между собой, поэтому дополнительно соединять их проводочком не требуется. На всякий случай стоит перепроверить, соединены ли пины, прозвонив их мультиметром.

Тонкости протокола

Итак, типичная команда выглядит как-то так:

Протокол SD-карт в PulseView

Команды всегда имеют формат 01xxxxxx, и в соответствии со значением битов xxxxxx называются CMD0, CMD1, и так далее до CMD63. Следом за командой идут 4 байта аргумента, за которыми идет байт в формате yyyyyyy1 с семибитным CRC. Контрольные суммы по умолчанию выключены и проверяются только для первых нескольких команд на этапе инициализации. В остальных же случаях CRC заполняется единицами.

Большинство команд получают в ответ один байт, так называемый R1:

/*
R1: 0abcdefg
||||||`- 1th bit (g): card is in idle state
|||||`-- 2th bit (f): erase sequence cleared
||||`--- 3th bit (e): illigal command detected
|||`---- 4th bit (d): crc check error
||`----- 5th bit (c): error in the sequence of erase commands
|`------ 6th bit (b): misaligned addres used in command
`------- 7th bit (a): command argument outside allowed range
(8th bit is always zero)
*/

Во-первых, вы можете помнить, что в SPI за один такт SCLK одновременно принимается и передается один бит информации. Так вот, оказывается, что если при чтении ответа от SD-карты случайно послать по SPI что-то отличное от единиц, некоторым SD-картам это рвет башню. Поэтому прием данных от карты выглядит как-то так:

Во-вторых, в статье верно описано, что в определенных случаях карта может помечать себя занятой (busy), притягивая MISO к земле. В таких ситуациях нужно дождаться готовности карты. Но на практике оказалось, что проверку на готовность нужно выполнять перед каждой командой, даже если в текущих обстоятельствах карта не может быть занятой. То есть, по сути, перед каждой командой нужно посылать 0 x FF (на иллюстрации с форматом команд этот момент опущен). Иначе некоторые карты отказываются работать. Я наблюдал такое поведение у карт производства SanDisc.

Fun fact! Понять я это смог, подглядев в Arduino-библиотеку SD. Пользуясь случаем, отмечу, что библиотека эта в целом довольно скверная. Мне не кажется очень хорошей идеей мешать в одну кучу код для SDSC и SDHC/SDXC карт, как сделано в этой библиотеке. Также я заметил, что в ней почему-то отсутствует поддержка CMD18 (READ_MULTIPLE_BLOCK), несмотря на то, что CMD25 (WRITE_MULTIPLE_BLOCK) реализована. И еще библиотека отказалась работать с некоторыми имеющимися у меня картами, несмотря на то, что код, написанный мной с нуля, прекрасно с ними работает. Вот и пользуйся после этого готовыми библиотеками!

Наконец, в третьих, карта может делить SPI-шину с другими устройствами. Понятно, что в этом случае первым делом после запуска прошивки нужно пометить все устройства, как неактивные, подав соответствующее напряжение, обычно высокое, на пины CS. После чего уже можно спокойно общаться с каждым устройством по отдельности, не беспокоясь, что какое-то другое устройство по ошибке решит, что обращались с нему. Но проблема заключается в том, что SD-карта определенным образом интерпретирует данные, передаваемые по SPI, даже не являясь выбранным устройством. Если конкретнее, то при инициализации карты нужно передать 74 или больше единицы (например, 10 байт 0 x FF) с высоким напряжением на CS. По этой причине карта либо должна жить на отдельной шине, либо инициироваться перед всеми остальными устройствами. Иначе карта может отказаться работать, я проверял.

Получившаяся библиотека

В ходе изучения мной протокола SD-карт была написана библиотека для STM32, реализующая этот протокол. Библиотека основана на HAL и имеет следующий интерфейс:

// all procedures return 0 on success, < 0 on failure
// size of block == 512 bytes

SD-карты могут реализовывать дополнительные функции, такие, как очистка блоков и защита блоков от записи. Но они поддерживаются не всеми картами, и потому не реализованы. Также протокол позволяет включить проверку контрольных сумм. Но эта возможность не реализована, поскольку данные могут испортиться не только во время передачи, и потому их целостность должна проверяться выше уровня протокола, на уровне конкретного приложения. Дополнительно вычисляя и проверяя CRC на уровне протокола мы, скорее всего, только зря скушаем миллиамперы и займем flash-память. Да и вообще, я не убежден в надежности семибитных CRC.

Заключение

В качестве источников дополнительной информации я бы рекомендовал следующие:

Полную версию исходников к этому посту вы найдете на GitHub. Обратите внимание, что тамошний пример кода пишет на карту на уровне блоков, ничего не зная ни о каких файловых системах. Поэтому, если решите его запускать, советую выбрать SD-карту без особо ценных данных.

Вооружившись полученными сегодня знаниями, можно реализовать много безумных идей. Например, можно сделать RAID из SD-карточек, или устройство с интерфейсом SD-карты, сжимающее и/или шифрующее данные. Или вообще отправляющее их на сервер по беспроводной связи. Конечно же, совершенно не был затронут вопрос работы с файловыми системами. Ему будет посвящена одна из следующих заметок.

На этом у меня пока все. А доводилось ли вам использовать SD-карты в своих проектах, и если да, то для каких задач?

SD карты (Secure Digital) - это формат карт флэш памяти. Был представлен в 1999 как улучшенный MMC. Стандарт SD регулирует "SD Association" (SDA). На их сайте можно найти документацию на стандарт.

Я постараюсь вкратце расписать, как использовать эту карту для хранения и считывания информации с помощью SPI. О том как работать с SPI расписано здесь.


Рис.1 SD карты различных размеров
По стандарту, у SD карт есть 3 возможных физических размера: стандартный, mini и micro:


Рис.2 различные типы размеров SD карт с замерами
Есть 4 поколения карт памяти, которые отличаются друг от друга размером хранимой информации, считыватели карт младших поколений не работают с более поздними версиями.

  • Шина SPI
  • Однобитовый режим шины SD
  • Четырёх битовый режим шины SD

В сети есть несколько открытых библиотек для работы с FAT (16/32), к примеру: FatFs, в таком случае можно считывать данные с компьютера, проверяются повреждённые блоки, память и ресурсы карты расходуются разумнее, ведь файловая система используется не просто так.

Но если всё это не так важно, можно не много памяти, которые выглядят как простой набор бит, то можно обойтись и без файловой системы, напрямую считывая и записывая данные. Только нужно помнить, что в SD картах информация хранится в блоках по 512 байт. Нужно считывать и записывать информацию блоками.

Можно создать текстовый документ, записать в него нужную информацию, открыть SD карту с помощью Hex-редактора, (к примеру: HxD) посмотреть в каком блоке (кластере) находится информация, (может быть она записана в нескольких блоках) считать её.

Считать байт можно и без файловой системы и специальных библиотек, но скорей всего нельзя записать информацию не повредив файловую систему, после неправильной записи компьютер может не распознать SD карту и предложит её отформатировать.

Можно попробовать создать текстовый документ на компьютере, записать в него что-то, затем найти блок с этой информацией и менять его. Не знаю какие в файловой системе реализован проверки, возможно нельзя изменить хранящиеся данные (там могут быть контрольные суммы для проверки).

SPI используется всего лишь как интерфейс, данные передаются по "урезанной" версии стандартного протокола SD карты.

Протокол передачи данных

К примеру мы хотим считать блок данных, это будет выглядеть следующим образом:


Рис.4 Считывание 1 блока данных (512 байт)
Рассмотрим что здесь изображено. Сперва хост по линии DataIn (MOSI) посылает команду карте. Рассмотрим из чего состоит "команда":


Рис.5 Формат команды
Команда состоит из 48 бит, начальный бит = "0", затем "1" означает, что это команда от хоста.
Биты передаются, начиная со старших разрядов.
Content - содержимое команды вместе с адресом или параметром (38 бит). Первые 6 бит определяют команду, остальные 32 это параметр команды, к примеру, ячейку с каким адресом прочитать из памяти.
CRC (Cyclic Redundancy Code) - помогает избегать ошибок при передаче, у каждой команды есть свой CRC код (контрольная сумма).
Стоп бит = "1".

Response - это ответ карты на команду, если он есть (есть команды без ответа), то он может быть 1 из 4 видов (R1, R2, R3, R6):


Рис.6 Формат ответа
Ответ может состоять из 48 или 136 бит. Передаются, также начиная со старших разрядов. Сперва начальный бит = "0". Затем "0" означающий, что это команда от карты. В содержимом может быть либо значение регистра, который мы хотели считать, стоит отметить, что регистр RCA не доступен в режиме SPI (R3), либо "зеркальный" код команды и информация о состоянии.

Data block - это 512 байт данных, которые мы хотели считать, после них идёт контрольная сумма (CRC) для проверки содержимого.

Вместе с командой нам нужно отправлять CRC код для проверки, он вычисляется с помощью алгоритма. Если использовать библиотеки для работы с SD картами и FAT, то там это уже всё реализовано. Если работать с нуля, нужно для каждой команды вычислять CRC код. Разберёмся, как это делать.

В SD картах используются CRC7 и CRC16 проверки, 16 редко используется, но смысл там тот же что и в 7, так что рассмотрим её, если нет желания возиться с CRC кодами их можно отключить командой CMD59.

Для того чтобы проверить результат нельзя использовать стандартный калькулятор Windows. Если перевести в десятичный код, то он даёт правильный ответ, но это не по правилам двоичной арифметики. Для проверки можно использовать, к примеру, этот калькулятор.

Подсчитаем CRC код для команды CMD0:

  • берём содержимое команды вместе с её индексом и битом, обозначающим от кого передача (0 в данном случае) получаем (индекс команды 0, аргумент 0): 1 000000 00000000000000000000000000000000
  • Сдвигаем число на 7 разрядов влево, получаем 1 000000 00000000000000000000000000000000 0000000
  • Полученное число делим на CRC7 полином "10001001" и берём остаток: 1 000000 00000000000000000000000000000000 0000000 % 10001001 = 1001010
Согласно даташиту именно такой CRC код у команды CMD0.

На самом деле деление затратно выполнять в цифровых устройствах, но в данном случае его легко реализовать как программно, так и аппаратно, при делении с остатком нужно реализовать лишь сдвиги и логическую операцию XOR, что выполняется быстро и не занимает много места.

Нам нужно записать наше число, сдвинуть его на 7 разрядов влево, затем сдвинуть наш полином таким образом, чтобы его крайняя левая "1" была под крайней левой "1" нашего большого числа. Затем произвести между двумя числами XOR (если разные значения в 1 разряде выставить 1, иначе 0). С полученным числом проделать то же самое (сдвинуть под крайнюю единицу полином, XOR) до тех пор пока у изначального числа (пока мы его не сдвигали влево на 7 разрядов) не будут все 0, иначе до тех пор пока биты [max : 8] не будут равны "0". Оставшиеся 7 бит и есть наш остаток.


Рис.7 Подсчёт остатка
Остаток 0x17.

Можно найти готовый код для подсчёта CRC7 значений, есть довольно много реализаций, к примеру: вот и вот.

Чаще всего используется ответ R1, он состоит из 8 бит, старший бит всегда выставлен в "0". Ошибка обозначается "1" в соответствующем бите. Структура R1 выглядит следующим образом:

  • (0 бит) in idle state - карта в состоянии ожидания и проводит процесс инициализации.
  • (1) erase reset - команда отмены удаления данных из памяти пришла до того как удаление началось.
  • (2) illegal command - неизвестный код команды.
  • (3) com crc error - ошибка проверки CRC кода.
  • (4) erase sequence error - ошибка в последовательных командах удаления.
  • (5) address error - неверный адрес.
  • (6) parameter error - неверный параметр.

В ответ на CMD13, карта отправляет R2, в дополнении к ошибкам в R1 здесь добавлено несколько новых:

  • (0 бит) Card is locked - карта заблокирована пользователем.
  • (1) Write protect erase skip | lock/unlock command failed - была попытка удалить блок, защищённый от записи, либо был введён неправильный пароль при блокировке/разблокировке карты.
  • (2) Error - стандартная или неизвестная ошибка произошла во время операции.
  • (3) CC error - ошибка контроллера карты.
  • (4) Card ECC failed - ECC код был использован, но не получилось восстановить данные.
  • (5) Write protect violation - была попытка записи в блок, защищенный от записи.
  • (6) Erase param - неправильно выбраны адреса для очистки блоков.
  • (7) Out of range - параметр выходит за границы карты.

Формат R7 используется когда мы меняем напряжение, но SPI может работать только при 3.3 В. В отличие от SD интерфейса, так что R7 можно не рассматривать.


Рис.10 Запись нескольких блоков в карту
На каждый записанный блок карта посылает ответный маркер:


Рис.11 Маркер записи блока данных
Значение битов "Status" следующее:

  • "010" - данные приняты.
  • "101" - данные отклонены из-за ошибки в CRC коде.
  • "110" - данные отклонены из-за ошибки в процессе записи.

Также есть маркеры определяющие начало и конец записи:


Рис.12 Маркер начала записи/считывания 1 блока, считывания нескольких блоков


Рис.13 Маркер начала записи нескольких блоков
При работе с несколькими блоками маркер посылается каждый раз перед передачей очередного блока данных.

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

Если карта не сможет прочитать блок данных, она отправит маркер ошибки, там обозначены те же биты, что и в R2:


Рис.15 Маркер ошибки считывания.
Биты обозначающие ошибки как в маркерах так и в ответах R* очищаются после того как они были переданы хосту, их не нужно очищать вручную.

В режиме SPI мы можем считать 3 регистра OCR CID и CSD. Рассмотрим, что в них хранится.

Регистр OCR отвечает за доступные режимы питания карты:


Рис.16 Содержимое регистра OCR.
В битах [23:15] единица означает, что карта поддерживает данное напряжение.

Регистр CID хранит информацию от производителя:


Рис.17 Содержимое регистра OCR
Регистр CSD состоит из 127 бит и хранит техническую информацию, максимальный ток, скорость записи, размер максимального блока для работы и т.д. Он может отличаться от карты к карте в зависимости от размера. Не буду его расписывать в документации на это потратили 11 страниц.

У карты больше регистров, но они не доступны в режиме SPI.

Заключение

Этой информации должно хватить, чтобы понять, как работать с SD картой. Но я рекомендую использовать готовые библиотеки для работы с FAT файловой системой, конечно нужно больше памяти и RAM, но зато не нужно разбираться с работой на низком уровне, остаётся лишь использовать готовые функции.

Популярная библиотека FatFs. Также у них есть версия меньшего размера для 8 битных МК Petit FAT.


Если вы думаете, что при покупке карт памяти для своих гаджетов нужно смотреть только на поддерживаемый формат и объём, придётся вас расстроить. Учитывать следует как минимум пять важных моментов.


Для большинства людей microSD — это лишь форм-фактор, но на самом деле это не так. Вы без проблем сможете вставить любую microSD-карту в стандартный слот, но далеко не каждая из них будет работать, поскольку карты различаются по множеству признаков.


Всего существует три различных формата SD, доступных в двух форм-факторах (SD и microSD):

SD (microSD) — накопители объёмом до 2 ГБ, работают с любым оборудованием;
SDHC (microSDHC) — накопители от 2 до 32 ГБ, работают на устройствах с поддержкой SDHC и SDXC;
SDXC (microSDXC) — накопители от 32 ГБ до 2 ТБ (на данный момент максимум 512 ГБ), работают только на устройствах с поддержкой SDXC.
Как видите, обратной совместимости у них нет. Карты памяти нового формата на старом оборудовании работать не будут.

Заявленная производителем поддержка microSDXC не означает поддержку карт этого формата с любым объёмом и зависит от конкретного устройства. Например, HTC One M9 работает с microSDXC, но официально поддерживает только карты до 128 ГБ включительно.

С объёмом накопителей связан ещё один важный момент. Все карты microSDXC используют по умолчанию файловую систему exFAT. Windows поддерживает её уже более 10 лет, в OS X она появилась начиная с версии 10.6.5 (Snow Leopard), в Linux-дистрибутивах поддержка exFAT реализована, но «из коробки» работает далеко не везде.

Высокоскоростной интерфейс UHS


Карты форматов SDHC и SDXC могут поддерживать интерфейс Ultra High Speed, который при наличии аппаратной поддержки на устройстве обеспечивает более высокие скорости (UHS-I до 104 МБ/с и UHS-II до 312 МБ/с). UHS обратно совместим с более ранними интерфейсами и может работать с не поддерживающими его устройствами, но на стандартной скорости (до 25 МБ/с).


Классификация скорости записи и чтения microSD-карт так же сложна, как их форматы и совместимость. Спецификации позволяют описывать скорость карт четырьмя способами, и, поскольку производители используют их все, возникает большая путаница.


Макрикровка класса скорости для обычных карт представляет собой цифру, вписанную в латинскую букву C

К классу скорости (Speed Class) привязана минимальная скорость записи на карту памяти в мегабайтах в секунду. Всего их четыре:

Class 2 — от 2 МБ/с;
Class 4 — от 4 МБ/с;
Class 6 — от 6 МБ/с;
Class 10 — от 10 МБ/с.


По аналогии с маркировкой обычных карт, класс скорости UHS-карт вписывается в латинскую букву U

У карт, работающих на высокоскоростной шине UHS, пока всего два класса скорости:

Class 1 (U1) — от 10 МБ/с;
Class 3 (U3) — от 30 МБ/с.
Поскольку в обозначении класса скорости используется минимальное значение записи, то теоретически карта второго класса вполне может быть быстрее карты четвёртого. Хотя, если это будет так, производитель, скорее всего, предпочтёт более явно указать этот факт.

Класса скорости вполне достаточно для сравнения карт при выборе, но некоторые производители помимо него используют в описании максимальную скорость в МБ/с, причём чаще даже не скорость записи (которая всегда ниже), а скорость чтения.

Обычно это результаты синтетических тестов в идеальных условиях, которые недостижимы при обычном использовании. На практике скорость зависит от многих факторов, поэтому не стоит ориентироваться на эту характеристику.

Ещё один вариант классификации — это множитель скорости, подобный тому, который использовался для указания скорости чтения и записи оптических дисков. Всего их более десяти, от 6х до 633х.

Множитель 1х равен 150 КБ/с, то есть у простейших 6х-карт скорость равна 900 КБ/с. У самых быстрых карт множитель может быть 633х, что составляет 95 МБ/с.


Правильно выбирать карту с учётом конкретных задач. Самая больша́я и самая быстрая не всегда лучшая. При определённых сценариях использования объём и скорость могут оказаться избыточными.

При покупке карты для смартфона объём играет большую роль, чем скорость. Плюсы большого накопителя очевидны, а вот преимущества высокой скорости передачи на смартфоне практически не ощущаются, поскольку там редко записываются и считываются файлы большого объёма (если только у вас не смартфон с поддержкой 4K-видео).

Камеры, снимающие HD- и 4K-видео, — это совсем другое дело: здесь одинаково важны и скорость, и объём. Для 4K-видео производители камер рекомендуют использовать карты UHS U3, для HD — обычные Class 10 или хотя бы Class 6.

Для фото многие профессионалы предпочитают пользоваться несколькими картами меньшего объёма, чтобы минимизировать риск потери всех снимков в форс-мажорных обстоятельствах. Что до скорости, то всё зависит от формата фото. Если вы снимаете в RAW, есть смысл потратиться на microSDHC или microSDXC класса UHS U1 и U3 — в этом случае они раскроют себя в полной мере.


Как бы банально это ни звучало, но купить подделку под видом оригинальных карт сейчас проще простого. Несколько лет назад SanDisk заявляла, что треть карт памяти SanDisk на рынке является контрафактной. Вряд ли ситуация сильно изменилась с того времени.

Чтобы избежать разочарования при покупке, достаточно руководствоваться здравым смыслом. Воздерживайтесь от покупки у продавцов, не заслуживающих доверия, и остерегайтесь предложений «оригинальных» карт, цена которых значительно ниже официальной.

Злоумышленники научились подделывать упаковку настолько хорошо, что порой её бывает очень сложно отличить от оригинальной. С полной уверенностью судить о подлинности той или иной карты можно лишь после проверки с помощью специальных утилит:

H2testw — для Windows;
F3 — для Mac и Linux.


Если вы уже сталкивались с потерей важных данных из-за поломки карты памяти по той или иной причине, то, когда дело дойдёт до выбора, вы, скорее всего, предпочтёте более дорогую карту известного бренда, чем доступный «ноунейм».

Помимо большей надёжности и сохранности ваших данных, с брендовой картой вы получите высокую скорость работы и гарантию (в некоторых случаях даже пожизненную).

Теперь вы знаете об SD-картах всё, что необходимо. Как видите, есть много вопросов, на которые вам придётся ответить перед покупкой карты. Пожалуй, наилучшей идеей будет иметь различные карты для различных нужд. Так вы сможете использовать все преимущества оборудования и не подвергать свой бюджет лишним расходам.

Читайте также: