Дёшево и сердито! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Азы работы с MMC
MMC карты имеют достаточно простое управление. Память разбита на сектора по 512 байт. Карты форматируются так же, как обычные винчестеры под DOS: с 1 разделом, файловая система - FAT16. Чтение возможно как отдельными байтами, так и блоками.
Напряжение питания карты должно быть в пределах +2.7в...+3.6В, скорость обмена до 20 мбит/с. При простое более 5мс карточка переводится в sleep режим с малым энергопотреблением, и выходит из него автоматически при возобновлении обмена. Интерфейс картыMMC карты могут работать в двух режимах обмена - MultiMediaCard protocol и SPI protocol.Первый более скоростной, а в пользу второго говорит то, что много контроллеров имеют встроенный SPI интерфейс. Ниже приведена разводка MMC именно для работы в режиме SPI:
Cигнал выборки имеет "0" активный уровень. SPI порт в управляющем контроллере (далее МК) должен быть настроен так, чтобы активным был передний фронт SCLK: Сразу же напомню о том, что фактически передача байта из контроллера (DO) осуществляется параллельно с приёмом по другой линии (DI). Чтобы начать приём/передачу через SPI в PICе (в Master mode), в буффер приёмопередатчика SSPBUF нужно что-то записать, а после окончания пересылки из SSPBUF считать принятое. В простейшем случае обмен с картой имеет вид "команда - ответ": Обозначения:1 клетка - 8 бит; X - произвольно, Z - третье состояние, H - 0xFF, L - 0x00; Тр = 1÷8 байт, Тотв = 1÷many байт. Внимание! Рисунки поясняют принцип обмена, поэтому масштабы не соблюдены! Обмен начинается с того, что МК выставляет сигнал 0 на xCS. Сначала посылаем 6 байт команды - последовательно пишем в вышеуказанный SSPBUF нужные байты, не забывая перед записью очередного дожидаться окончания передачи предыдущего (бит SSPSTAT,BF). Далее нужно дождаться ответа карты: пишем в SPI байт 0xFF и по окончании каждой передачи (контролируем SSPSTAT,BF) читаем принятое в SSPBUF. Первый байт, отличный от 0xFF, будет первым байтом ответа карточки (а для рассматриваемых ниже команд ответ всегда состоит из 1 байта). Данные, если требуется, передаются после ответа блоком заданной ранее длины: Начало блока данных "ловится" так-же: его первый байт отличен от 0xff (см. ниже).После окончания обмена нужно подать 1 на xCS. Команды и ответыКоманда имеет длину 6 байт, передача всегда начинается со старшего бита. Пакет команды имеет следующий формат:
При работе MMC в режиме SPI доступно около 15 команд, позволяющих во-первых получить полную информацию о типе и текущем состоянии карты, во-вторых производить запись и чтение данных. Рассмотрим всего лишь 4 команды, с помощью которых можно лишь читать данные с MMC блоками размером 1÷512 байт (мне для плеера вполне хватает):
Ответ на любую из вышеприведённых команд состоит из одного байта, старший байт всегда равен 0. Другие биты - флаги ошибок:
Блок данных имеет длину от 4 до N+3 байт, где N - число, указанное в аргументе CMD16. Первый байт при передаче от MMC к МК равен 0xFE, далее следуют N байт запрашиваемой информации, а в конце - 2 байта CRC (их содержимое можно игнорировать, но прочесть нужно обязательно!). Если же при чтении произошёл сбой и карта не может предоставить данные, то вместо указанного блока передаётся 1 байт с флагом ошибки:
Инициализация картыПосле включения карта находится в режиме MultimediaCard protocol. Для перевода её в режим SPI надо отправить команду Сброс (CMD0) (не забывайте про xCS). В режиме SPI проверка CRC отключена по умолчанию, поэтому содержимое поля CRC7 игнорируется. Однако для CMD0 поле CRC7 нужно указать правильно. Поскольку команда не имеет меняющихся в процессе работы аргументов, то и специально вычислять это поле не обязательно: правильная CMD0 имеет вид: 0x40, 0x0, 0x0, 0x0, 0x0, 0x95. Далее карту необходимо проинициализировать. Для этого посылаем команду CMD1 до тех пор, пока в ответе карты бит0 (в спящем режиме) не сменится с 1 на 0. Это будет означать, что карта готова к работе. Теперь можно посылать прочие команды (у нас это CMD16 и CMD17).Файловая cистемаСамое интересное - это работа с файловой системой. Не буду сильно распространяться, т.к. в инете итак навалом информации о том, что такое FAT16 и с чем её едят. Кратенько расскажу о том, как использовать содержимое некоторых секторов в своих личных целях ;)Структура диска:
MBR находится в нулевом секторе диска, позиции остальных частей будем вычислять. Нулевой сектор, он же Master Boot Record диска, выглядит примерно так:
Нам нужно описание первого раздела (то, что по смещению 0x1BE).Что там есть:
Это, конечно, не всё, но этого вполне хватит. Как пример привожу то, что написано в моей карточке: Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................ 000001C0 01 00 06 07 E0 D3 20 00 00 00 E0 D3 03 00 00 00 ....аУ ...аУ....Здесь позиция PBR - сектор номер 0x00000020, а число секторов 0x0003D3E0 (все длинные числа записаны с младшего байта), Offset - смещение байта от начала диска. Не стоит забывать, что физический адрес PBR равен pbr_adr = 0x00000020 * 0x200 =0x00004000 (0x200 - число байт на сектор). Идём в Partition Boot Record раздела:
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00004000 EB 00 90 20 20 20 20 20 20 20 20 00 02 04 01 00 л.ђ ..... 00004010 02 00 02 00 00 F8 F5 00 20 00 08 00 20 00 00 00 .....шх. ... ... 00004020 E0 D3 03 00 80 00 29 A9 3D 30 FC 4E 4F 20 4E 41 аУ..Ђ.)©=0ьNO NAМы видим 0x04 сектора на кластер, 0x00F5 секторов на каждую FAT, под PBR отведён 1 сектор, 512 записей в корневом каталоге. Этих четырёх чисел хватит, чтобы вычислить 3 важных смещения:
Все смещения есть, осталось совсем немного. Разберёмся с FAT. Во первых всё пространство диска (после Root Dir) поделено на т.н. кластеры по "Sectors_per_Cluster" секторов в каждом. Во вторых 2 копии FAT идентичны, поэтому будем работать с первой. А FAT состоит из последовательности 2-х байтных слов (МЛАДШИЙ байт впереди). N-ое слово соответствует N-ому кластеру (N>1), и может содержать следующую информацию:
Исходя из разбиения диска на кластеры файл, будь он больше размера одного кластера, естественно содержит их несколько штук. Последовательность номеров кластеров, в которых записан файл, образует цепочку кластеров. Цепочка строится так: номер первого читается из записи в каталоге; в соответствующем слове FAT при этом указан следующий кластер. В слове для следующего - номер третьего и т.д. пока не достигается конец цепочки. Маленький организационный момент: первые 4 байта FAT - обязательная подпись, означает, что это начало FAT. Поэтому Нет нулевого и первого слова, Нет нулевого и первого кластеров, сразу за RootDir сидит кластер номер 0002. И снова от теории к практике - придуманное мной для примера начало FAT: Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 00004200 F8 FF FF FF 03 00 05 00 06 00 04 00 07 00 FF FF шяяя..........яяПервые 4 байта - подпись. Допустим, файл начинается со 2 кластера, Num = 2. Тогда адрес этого кластера adr = Cluster_base + Num * Sectors_per_cluster * 0x200. Кластер мы прочитали, а дальше читаем слово в FAT для этого кластера, 2 байта начиная с адреса adr = Fat_base + Num * 2 (0x4204). В нашем случае это 0003 - номер следующего кластера (см. таблицу). Расшифроывая таким образом содержимое Fat получим цепочку: 0002 - первый,0003,0005,0004,0006,0007 - последний. Если разобраться - достаточно просто. Наконец заглянем в корневой каталог - там кроме имени файла, даты, времени, атрибутов, указан первый кластер файла и его размер в байтах. Каждая запись в корневом каталоге состоит из 32 байт. Нам нужно прочитать байты со смещением 0x00,0x02,0x1A-0x1B,0x1C-0x1F. Если нулевой байт не равен 0xE5, второй не равен 0x00 или 0x04, то 0x1B:0x1A - первый кластер файла, а 0x1F:0x1E:0x1D:0x1C - его размер в байтах. Пока плеер без экрана, имя файла получать не обязательно... P.S.: Как выяснилось, SD карты полностью совместимы с карточками MMC, в т.ч. в режиме SPI. "Лишние" выводы в этом режиме не используются:
Единственно что стоит сделать - поставить подтягивающие сопротивления на выв. 8 и 9 (в р-не неск. деятков кОм). Основная часть составлена по материалам "MultiMedia Card product manual v5.2", с сайта SanDisk. Тем, кто захочет поподробнее разобрать данный вопрос, рекомендую обратиться к означенному документу. Datasheet на SD взят с того-же сайта :"SanDisk SD card product manual v1.9". О замеченных очепятках и неточностях прошу писать мне. |