nabbla (nabbla1) wrote,
nabbla
nabbla1

Categories:

QuatCore: контроллер SPI для SD-карточек

Всю неделю копался в документации по SD-карточкам. Начал с этого официального талмуда, Physical Layer Simplified Specification. Там, к сожалению, напрочь отсутствовала важная глава, SPI bus timing diagrams, вместо этого одна строка: This section is left blank in the Simplified Specification. Полная спецификация стоит совершенно зверских денег, вроде под 2 тыщи баксов.

Но вроде бы нашёл что нужно в SanDisk Secure Digital Card Product Manual. По крайней мере, вместо конкретных цифр "сколько байт выжидает НАША карточка, прежде чем даст ответ на команду", там приведены ответы в широких пределах, поэтому я подозреваю, что тайминги они взяли официальные, ну а зачем себя искусственно ограничивать :)

Казалось бы: SPI он и в Африке SPI, говорить "SPI для SD-карточек" - это бред, на физическом уровне всё должно быть то же самое! Но я бы так не сказал: зная специфику этого обмена, можно существенно упростить работу модуля и управление им.



Никогда не отключаем SCK!
Кажется, что если ни одно устройство на шине не задействовано, надо отключить тактовую частоту, шина она же всё-таки большая, зачем по чём зря раскачивать такую ёмкостную нагрузку (How DARE you!). Именно так вёл себя мой контроллер SPI для АЦП и для Ethernet-контроллера.

Но в пункте 6.4.1.1 спецификации сказано, что от момента выхода напряжения питания карточки на минимально допустимый уровень до начала информационного обмена мы должны подать на выход SCK по крайней мере 74 импульса тактовой частоты для какой-то внутренней инициализации. В этот момент на входе CS (chip select) и MOSI (Master Out Slave In) должна сохраняться единичка, т.е чип пока ещё не выбран, но тактовая частота ему необходима.

Далее, в пункте 4.4 спецификации, а также в пункте 5.1.8 из Product Manual сказано, что после получения ответа от карточки, мы должны подать ещё хотя бы 8 импульсов тактовой частоты, причём состояние CS в этот момент неважно.

Самый простой способ выполнить эти требования - всегда подавать тактовую частоту на SCK. Потом можно будет в порядке бреда померить энергопотребление при включенном и выключенном SCK и всё-таки отрубать её, а пока что лениво.

Помесь SPI и UART
Хотя изначально SPI является синхронным интерфейсом, карточке SD дали возможность отвечать на команду, когда она сочтёт нужным. Она может присылать ответ СРАЗУ же, или подождать от 1 до 8 байта. Пока она не передаёт, на проводе MISO (Master In Slave Out) висит лог. единица, тогда как все ответы начинаются с нулевого бита, что подозрительно напоминает стартовый бит в UART. Если мы научим свой SPI контроллер игнорировать эти "пустые" байты 0xFF, то работа заметно упростится, не придётся повсюду программировать циклы ожидания наподобие
while (SPI.transfer(0xFF)!=0x01);
.

Работа по 16 бит вместо 8 бит
Свобода отвечать "не сразу" дана не только карточке SD, но и хосту, то есть нам. Все команды (и токен, предваряющий передачу данных) начинаются нулевым битом, а перед ними мы можем отправить сколько угодно "пустых" байтов 0xFF.

Одно из следствий - даже если где-то нужно будет передать нечётное количество байт, мы можем добавить один "пустой" байт в начало посылки - и она будет корректной. Поэтому предлагается не мелочиться и отправлять на контроллер по 16 бит за раз, по ширине нашей шины данных.

То же самое верно относительно получения информации: даже если ответ предполагает всего один байт, мы с чистой совестью можем удерживать CS на нуле и дождаться получения ещё одного "пустого байта" - сказано же, что состояние CS при передаче очередных 8 импульсов тактовой частоты НЕСУЩЕСТВЕННО.

Полудуплексная работа
Сам по себе интерфейс SPI - дуплексный, и мы наблюдали это при работе с АЦП: не успели мы ещё передать один байт, содержащий номер канала, который надо оцифровать, как "навстречу" по проводу MISO уже идёт оцифрованное значение с предыдущего такта!

Но при работе с SD-карточками этого не используется: когда мы посылаем команду, по MISO ничего не поступает, а когда мы принимаем ответ или данные, то молчим сами.

Сам по себе сдвиговый регистр от этого наблюдения не упрощается - ему всё равно, как работать. Но зато такая работа замечательно "ложится" на команды IN на SrcAddr и OUT на DestAddr.

В прошлый раз мы поставили модуль QuatCoreIOselector (селектор ввода-вывода), и в нём остались незадействованные выводы для подключения нашего контроллера SPI, а именно:
SDtxEN
и
SDrxEN
. Единичка по первому запускает контроллер на передачу, по второму - на приём.

Заголовок (интерфейс) нашего контроллера должен выглядеть так:

module QuatCoreSD_SPI (	input clk, input [15:0] D, input TXen, input RXen,
			inout MISO,
			output [15:0] Q,
			output SCK, output MOSI, output nCS, output busy);

parameter clkFreq = 4_000_000;
parameter SDfreq = 400_000;


В кои-то веки он "висит" на шине данных "с обеих сторон". В режиме передачи мы заносим данные по входу D из шины данных, а в режиме приёма они появляются на выходе Q, который через мультиплексор присоединяется к шине данных.

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

MISO объявлен как двунаправленный, поскольку при nCS=1 соответствующий выход SD-карты переходит в состояние с высоким выходным сопротивлением (Z), а "висящие в воздухе" провода мы не любим.

Пока что мы сделаем постоянную частоту SCK в 400 кГц. Положено начинать работу на частотах от 100 до 400 кГц, а по окончании инициализации можно и "разогнаться" вплоть до 25 МГц. В скором времени нам предстоит преодолевать clock domains, чтобы обработчик видео мог работать на 50 МГц вместе с контроллером SPI, тогда как процессор - на своих 4 МГц.

В принципе, наш процессор разгоняется до 28 МГц относительно легко, надо лишь поставить регистры на выходе ROM и мультиплексора данных, а также на входе RAM, затем поставить 8-битный регистр для DestAddr, чтобы адрес получателя задерживался на тот же такт, на который задерживается появление данных на шине, и добавить ещё пару цепей формирования stall, когда наступает прыжок, и ещё научить компилятор находить Hazard'ы, когда одна команда пытается использовать значения, которые к этому моменту ещё не успела получить предыдущая - и хотя бы грязно на это ругаться, а может самостоятельно вставлять NOPы.

Но до 50 МГц разогнать процессор на этой ПЛИС (5576ХС4Т) уже тяжело, это надо практически ВСЕ комбинаторные цепи укорачивать, разбивать на несколько частей. Пока я вообще не очень понимаю, что из этого получится. Тупо 32-битный сумматор у меня на такой частоте не заработает - задержка переноса по всем разрядам не укладывается. Мы искали способы борьбы, но тогда это был "одинокий сумматор" и "одинокий умножитель", а здесь это целое АЛУ, у которого уже весьма нетривиальные управляющие сигналы, а так вообще будет мама не горюй. Пока не хочу.

Впрочем, мы отвлеклись... Пока попробуем просто неторопливо "поговорить" с SD-карточкой.


Продолжение следует...

Poll #2098958 Разные тактовые частоты

Наш процессор пока работает на 4 МГц, а видеообработчик-на 50 МГц. Что делать?

Разогнать процессор до 50 МГц!
2(40.0%)
Сделать crossing clock domains через регистры
1(20.0%)
Всё взаимодействие сделать через модули двухпортовой памяти
2(40.0%)
Tags: ПЛИС, программки, работа, странные девайсы
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 2 comments