Open Logic Sniffer в действии

5 декабря 2010, воскресенье 16:19
Open Logic Sniffer в действии
Open Logic Sniffer in action


из серии "Моя борьба с микроконтроллерами"

(продолжение темы «Куда уходят миллисекунды. Повышаем FPS»)

В выпуске:
Логический анализатор OLS
«Правильное» программирование, С vs Asm, стили и т.д. и т.п.
Параллельное подключение LCD на 8-битную шину — определяем практический предел быстродействия
16 битная шина
Итог



Логический анализатор OLS

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

Логический анализатор в цифровых цепях, не требующих контроля формы сигнала, существенно снижает стоимость отладочного оборудования, ибо стоимость даже двухканального осциллоскопа с 200Msps становится четырехзначной в долларах США. А OLS за 50 долларов дает возможность с таким сэмплированием контролировать 16 линий, что позволяет отлаживать аппаратные конфигурации, функционирующие с частотами до 100MHz.

Для протоколов SPI, I2C и UART имеются специальные режимы захвата и анализа.

До сих пор я обходился двухканальным детским цифровым запоминающим осцилллографом с 25Msps, но это давно уже стало узким местом, прежде всего по отсутствию внешнего запуска, затем по числу каналов и частотам.

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

Детальный внешний вид OLS и пример работы по сканированию некоторой периферии приведены на сайте gadgetfactory , там же есть ссылки на аппаратно-программную часть и форум.

Логический анализатор может одновременно контролировать 32 цифровых линии с частотой сэмплирования до 100MHz или 16 линий с частотой сэмплирования до 200MHz, устройство разработано по мотивам и совместимо с программной частью открытого логического анализатора SUMP.

Сердцем устройства является FPGA Xilinx Spartan-3E, для связи с ПК установлен микроконтроллер от Microchip.

Из-за появления OLS стенд на базе ZP-STM32 было решено переконфигурировать на параллельное восьмибитное подключение к LCD, с целью попрактиковаться с OLS.

На торце OLS распаяна угловая гребенка на 16 контактов — буферизованных входов с толерантностью до 5V. Есть еще 16 небуферизованных контактов (работающих на вход и выход, колодка нераспаяна) с толерантностью до 3.3V.
Распаянная колодка делает очень удобным его установку в отладочную плату типа breadboard:


Сниффер установлен на отладочной плате

Вид на сниффер, установленный на бредборд, со стороны деталей:


OLS со стороны деталей

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


И это все надо в век беспроводных технологий?!

Сниффер был подключен на младшие 8-бит порта A ( МК STM32F103C8), т.е. на шину данных LCD D0..D7, еще пять входов — на управляющие сигналы LCD, три оставшиеся буферизованных входа использованы как триггеры запуска.

LCD переключается на параллельный режим очень просто — на обратной стороне платы дисплея есть SMD-шный DIP-переключатель для выбора режима:


Обратная сторона дисплейного модуля

Несчастному контроллеру тачскрина AR1020 от Microchip не повезло — случайно сколол чип, и он перестал реагировать на входные сигналы, хотя по интерфейсу отзывается, принимает и передает. То есть передает, что нечего передавать и пришлось его отключить.


Умер молодым

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


«Правильное» программирование, С vs Asm, стили и т.д. и т.п.

Прежде, чем приступить к практическому применению OLS, хочется затронуть извечную общую тему про программирование.

В моих экспериментах нет никаких табу. Я волен делать с программой все, что мне заблагорассудится. Впрочем, так ведет себя подавляющее большинство, с ограничениями по собственной квалификации. Другое дело, когда пишется код, соответствующий спецификациям MISRA, при этом, например, вы лишаетесь права использовать инлайновые ассемблерные вставки, они должны вызываться только в виде С-функции. Или же вынуждены следовать техническому заданию. Но мы будем придерживаться одного правила - «вот так, кажется, получше будет», что может быть в принципе хуже или неправильно с любых других точек зрения. Это простительно, так как я сам не являюсь программистом (хотя и не считаю таковыми многих, кто сам называет себя программистом и получает за это деньги).

Другими словами, «правильное» программирование призвано минимизировать потенциально возможный вред, так как считается, что человек — главная опасность при управлении машиной (любой) или написании для нее программы работы. Это считается вполне справедливо. Но именно поэтому большинство правил, законов и ограничений устанавливается на очень «средний уровень» квалификации и навыков. Применительно к программированию и нашему случаю — на выбранном аппаратном обеспечении и программируя на С «правильно» мы плавную полноэкранную анимацию никогда не увидим.

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

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

И еще один момент. Стиль программирования, одним из элементов которого является оформление программы, у каждого вырабатывается свой. В свое время я так и не принял венгерскую нотацию, константы по-прежнему пишу заглавными буквами, открывающая фигурная скобка всегда на новой строке (если не совсем короткое тело, тогда все в одну строку). Так, кстати, рекомендует делать официальная документация по GNU C. Но в наш век облегченного образования кого это волнует? На чтение документации у современного молодого поколения нет ни терпения, ни времени. (Так во все времена брюзжит старшее поколение, но все же деградация «постсоветского» образования видна невооруженным глазом).

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

Переходим к практике. С помощью OLS посмотрим, какое быстродействие у параллельной шины 72MHz STM32 с учетом необходимости формирования управляющих сигналов для LCD (параллельно по отдельной шине). Все делается исключительно с иллюстративной точки зрения работы OLS, так как на самом достаточно обычного калькулятора, а инженеры старой закалки могут обойтись и вовсе без него.


Параллельное подключение LCD — определяем практический предел быстродействия

Многоканальный контроль цифровых сигналов дает возможность быстро определить оптимальные или предельные режимы при конструировании. Для примера, рассмотрим, что можно ожидать от связки LCD MI0283QT-2 и STM32F103C8 при 8-битном параллельном подключении. Вернее, если посмотреть на технические данные контроллера HX8347D, установленного в LCD, то задачу надо поставить так : «что можно выжать из связки STM32F103C8 и программной реализации?». LCD можно не учитывать, так как цикл записи у HX8347D при таком подключении 66нс с временами Thigh и Tlow пульса nWR по 15нс и, при программировании на «чистом С», выйти за пределы таймингов LCD на такте MCU 72MHz не получится.

Для такой задачи даже не нужно подключать LCD, так как он работает в режиме «пассивного потребителя данных» и никаких сигналов в электирическую цепь не возвращает, а влянием отсутствия RLС нагрузки на шину, соответствующей LCD, можно пренебречь.

Но «бездевайсное» исследование можно делать далеко не всегда, особенно если использовать только логический анализатор. Например, когда нелинейность цепей оказывает существенное влияние на форму сигнала - при наличии импульсных устройств (а ведь нужно контролировать и негативный выброс). Чтобы в этом убедиться, в простейшем случае можно посмотреть влияние входной емкости на интерфейсе I2C, манипулируя номиналом подтягивающего резистора шины. Да и никто не сказал, что пороги изменения логического состояния у FPGA и тестируемого оборудования совпадают, они наверняка будут различаться. Не надо забывать и о погрешностях округления при вычислении и представлении данных. Впрочем, современные САПР дают достаточно точную картину того, что будет твориться в цепях и без дополнительного оборудования.

В нашем случае задействуем все буферизованные входы OLS, 8-битная шина данных, пять управляющих сигналов и три линии запуска.

В качестве программного интерфейса с ПК будет выступать альтернативная версия клиентской программы OLS, http://www.lxtreme.nl/ols/, так как, несмотря на ряд недостатков (что бросилось в глаза за два дня, даже уже пообщался с автором), визуально она более выигрышна.

Начнем с простейшей тестовой программы. Инициализируем шестнадцатибайтовый массив числами от 0 до 15, а в непрерывном цикле будем считывать значения этого массива и выводить полученное значение в порт А микропроцессора. Поэтому четыре старших разряда порта будут нулевыми, управляющие линии пока не используются, запуск анализатора делаем по высокому уровню на линии TRIG1. Листинг программы приведен ниже:

int main(void)

{
GPIO_Config();

uint8_t buf[16];
uint32_t j;

for (j=0; j<16; j++)
{
buf[j]=j;
}

TRIG1H;
TRIG1L;

for(;;)
{
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[0];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[1];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[2];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[3];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[4];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[5];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[6];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[7];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[8];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[9];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[10];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[11];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[12];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[13];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[14];
GPIOA->ODR = ((GPIOA->ODR) & 0xff00 ) | buf[15];
}
}


Сброс триггера нужен для того, чтобы его срабатывание происходило при нажатии кнопки сброса у МК. Триггер запуска может быть достаточно сложным, можно запрограммировать несколько уровней вложенности с дополнительными условиями. В нашем случае использован самый простой вариант.

Запись производится в младшие 8 битов порта, состояние старших битов сохраняется, для чего мы еще делаем вынужденную операцию чтения. Для максимального быстродействия операции записи развернуты на 16 штук в теле цикла, никаких дополнительных операций не производится, прерывания запрещены.В реальных программах вывода графики цикл может разворачиваться на 64 и более операци записи.

Запустив анализатор, получим следующую картинку:


Первое включение OLS


На графике D0 видно, что каждое 16 число находится на шине на 70% дольше остальных, то есть, в это время происходит инкремент (в реальной программе, где это возможно, естественно, декремент) счетчика и сравнение с условием завершения цикла. В нашем случае ни того, ни другого нет, но это в листинге программы, внутренние структуры все равно инициализируются и проверяются условия. Поэтому чем больше разница этих длительностей, тем больший выигрыш можно получить.

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

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

Поскольку 8-битный параллельный доступ к LCD не имеет практического смысла на данном МК, а старшие биты порта А пока не используются, уберем из цикла операцию чтения
GPIOA->ODR) & 0xff00,


оставив только
GPIOA->ODR = buf[j];.


Посмотрим, что получается, заодно поставим самое лучшее разрешение по времени - на верхней шкале цена деления 5 наносекунд:


Временной шаг - 5нс/дел



Время вывода в порт сократилось более, чем в три раза. Таким образом, восьмибитная шина обеспечивает пропускную способность более 14 мегабайт в секунду, 16-битная шина — более 28 мегабайт в секунду против максимальной теоретической производительности SPI на STM32 18 мегабит/c. Более, чем десятикратный рост, но об этом уже было сказано в предыдущей заметке.

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

Но пропускная способность шины вовсе не означает, что по ней удастся передать именно максимальный поток данных. Мы пока не рассматривали управляющие сигналы, а МК их выдает (или получает) , затрачивая дополнительные такты перед и после появления данных на шине.В то же время в SPI уже «все включено». Но об этом позже.

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

GPIOA->ODR = х

для потокового вывода.

Без знания ассемблера дальше не обойтись. Вернее, можно обойтись, поставив на этом точку. Характерны при этом «советы» одного участника форума (в самом начале моей ветке про МК), проповедующего исключительность применение языка С для МК. Для многих задач, безусловно, можно обойтись и без этого и вообще не знать системы команд МК. Только при этом можно будет писать только заурядные программы школьного уровня. Знание ассемблера требуется для качественного программирования на языке высокого уровня, а как иначе понять механизм «atomic» операций, формат стековых кадров и многие другие нюансы, влияющие на архитектуру программы? Люди, понимающие в программировании и создающие нормальные программы на «чистом» С, с такими тезисами не выступают.

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

...

TRIG1H;
0x08000280 <main+64>: movw r0, #3072; 0xc00
0x08000284 <main+68>: movt r0, #16385; 0x4001
0x08000288 <main+72>: mov.w r1, #256; 0x100
0x0800028c <main+76>: mov.w r2, #1
0x08000290 <main+80>: bl 0x800087c <GPIO_WriteBit>
TRIG1L;
0x08000294 <main+84>: movw r0, #3072; 0xc00
0x08000298 <main+88>: movt r0, #16385; 0x4001
0x0800029c <main+92>: mov.w r1, #256; 0x100
0x080002a0 <main+96>: mov.w r2, #0
0x080002a4 <main+100>: bl 0x800087c <GPIO_WriteBit>
GPIOA->ODR = buf[0];
0x080002a8 <main+104>: movw r3, #2048; 0x800
0x080002ac <main+108>: movt r3, #16385; 0x4001
0x080002b0 <main+112>: ldrb.w r2, [r7, #624]; 0x270
0x080002b4 <main+116>: str r2, [r3, #12]
GPIOA->ODR = buf[1];
0x080002b6 <main+118>: movw r3, #2048; 0x800
0x080002ba <main+122>: movt r3, #16385; 0x4001
0x080002be <main+126>: ldrb.w r2, [r7, #625]; 0x271
0x080002c2 <main+130>: str r2, [r3, #12]

...


МК серии Cortex поддерживают управление битовыми полями для набортной статической памяти (суммарно до 1МБ) и столько же для периферии, включая и порты ввода-вывода. Это делается путем добавления союзной (соответствующей, привязанной, связанной, комплементарной — я русскоязычную литературу не читаю и не знаю, какой термин общепринят) группы адресов, в 32 раза (по числу разрядов МК, чтобы не прибегать ко всякого рода кастингам, смещениям и логическим преобразованиям) превышающем область тех адресов памяти, для которой предусмотрены прямые операции с битовыми полями. Благо что адресное пространство МК 4ГБ. То есть, блоку адресов периферии размером в 1МБ соответствует союзный блок адресов в 32МБ. Запись 0 или 1 по созному адресу приводит к изменению соответствующего битового поля конкретного адреса периферии.

Фрагмент дизассемблированной программы начинается со взвода триггеров (для запуска OLS) и показан для вывода в порт двух первых чисел из буфера. Триггеры для изменения логического состояния используют стандартную периферийную библиотеку STM и, после инициализации базового адреса порта в регистре r0 и данных для вычисления адреса изменяемого бита, вызвают функцию GPIO_WriteBit. На это потребуется 560нс.

Операция записи байта в порт,

GPIOA->ODR = buf[j];,



на ассемблере по логике построения будет аналогична записи в союзную область и состоит из 4 ассемблерных команды, общей длительностью (1/72Mhz)*5 c (так как инструкция ldrb.w требует двух тактов процессора, а str, в данном случае, — один такт), т.е. чуть больше 70нс. Таким образом, все протсходит в восемь и более раз быстрее.

Но и это не предел.

Пара команд

movw   r0, #3072; 0xc00

movt r0, #16385; 0x4001,


формирующая стандартный для Cortex-M3 базовый адрес порта А 0х40010с00, одинаковая для каждой команды записи в порт, нужна только один раз. Это дополнительно сократит время записи в порт почти вдвое. При этом нужно будет использовать инлайновый ассемблер. Можно это сделать и вместе с самим циклом.

К слову сказать, более изящные по синтаксису С конструкции с указателем и смещением дадут пять ассемблерных команд, указателя с постинкрементом — восемь.

Управляющие команды - запись, чтение и признак команда/данные, итоговый результат которых — изменение битового поля, на ассемблере вообще могут представлять из себя одну команду, длительностью даже меньше разрешенных для дисплея MI0283QT-2 15нс.

Но, поскольку параллельное подключение к «обычному» порту МК не будет являться конечным вариантом подключения LCD, описанной выше ассемблерной оптимизации проводить не будем. На новой плате будет RGB-подключение через контроллер FSMC. Хотя там планируется «мультимониторная» конфигурация. И даже мультипроцессорная. Но об этом в другой раз.

Для иллюстрации посмотрим, как OLS визуализует код инициализации LCD MI0283QT-2.

Вот реальный код из программы:

void LCD_Init()

{
LCD_RSTL;
delay(50);

LCD_RSTL;
delay(50);

LCD_WriteReg (OSC_CTRL1, 1<<OSC_EN);
LCD_WriteReg (POWER_CTRL3, (1<<AP1)|(1<<AP0));
LCD_WriteReg (POWER_CTRL6, (1<<GASEN) | (1<<DK));
LCD_WriteReg (POWER_CTRL6, 0);
LCD_WriteReg (POWER_CTRL6, 1<<PON);
LCD_WriteReg (POWER_CTRL6, (1<<PON)|(1<<VCOMG));
LCD_WriteReg (DISPLAY_CTRL3, (1<<GON)|(1<<DTE)|(1<<D1)|(1<<D0));
LCD_WriteReg (COLMOD, MODE_16bpp);
LCD_WriteReg (MEMORY_CTRL, (1<<MV)|(1<<BGR));
}


Не могу сказать еще раз о стиле. Если посмотреть, как оформлены коды инициализации различных дисплеев от STM, Atmel и прочих вендоров, то это вряд ли похоже на язык высокого уровня — все параметры записываются только в виде чисел, то есть просто номера регистров и данные, без единого намека на функционал той или иной команды. На мой взгляд, это не правильный подход, тем более для обучающего материала. Заголовочный файл, который я написал для примененного дисплея MI0283QT-2 можно скачать отсюда. Он приведен не как образец исполения, а для того, чтобы сократить кому-то время написания своего драйвера под контроллер HX8347D.

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

Например, первая строчка записи в регистр LCD:

LCD_WriteReg (OSC_CTRL1, 1<<OSC_EN);


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

LCD_WriteReg (0х19, 0х01);


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

Перед строкой запуска осциллятора ставим триггерное условие запуска по высокому уровню TRIG1 и TRIG3 и низкому TRIG2, после обновления прошивки и сброса OLS выдает следующую картинку:


Инициализация дисплея MI0283QT-2



Цена деления времени — 25нс. Прекрасно видна работа функции записи по стробу LCD_WR, сначала индекса регистра (0х19) при низком уровне LCD_RS, затем значения этого регистра (0х01). При высоком уровне на линии LCD_RS записываются данные.

16 битная шина

Хоть сначала и не планировал, но не удержался и пересобрал стенд на 16-битное подключение к LCD:


Подключаем к OLS 16-битную шину

На ZP-STM32 высвободить 16 линий от одного порта (чтобы не заниматься ненужной программной группировкой) можно только для порта В, так как два вывода порта А используются под отладочный порт SWD, а еще два не имеют контактов для подсоединения, так как отданы исключительно под USB.

Для высвобождения порта В в начале программы следует разместить строку

GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);,

которая оставит только отладочный порт SWD, а выводы порта 3 и 4, ранее служившие TDO JRST для JTAG-интерфейса, освободятся как GPIO. Также при этом высвободится 15-й вывод порта А, бывший ранее TDI.

При этом нужно учесть, что в технической документации STM (Doc ID 13587 Rev 12, June2010), на 30 странице в таблице 5 содержится ошибка, так как показано, что GPIO функции вторичны по отношению к JTAG и работа этих выводов как обычных портов — это альтернативная функция (AF). Но, если высвобождаемые выводы при запрете JTAG конфигурировать как GPIO_Mode_AF_PP, то работать они не будут. Надо было прямо указать в документации, что при этом их нужно конфигурировать как обычные GPIO. Как говорится, доверяй, но проверяй.

На фото видно, как с колодки JTAG-разъема выходят красный и синий провода, которые и являются этими выводами 3 и 4 порта В. Коричневый провод — это вывод 2 порта В, он на отдельной колодке, так как служит еще и как boot1. Серый провод идет на внешнюю кнопку сброса.

К сожалению, при таком подключении мы лишаемся обоих портов I2C, остается только первый SPI (4 вывода), выводы PA0..PA7, PA15 и обрезок из трех линий порта C. Три линии необходимы для управления LCD, еще три заберем на триггеры запуска, а два вывода порта С - на RTC.
Итого на все остальное — три вывода. Но это у нас кратковременная учебная конфигурация.

Зато есть повод припаять на OLS колодку к небуферизованной 16-битной шине и посмотреть одновременно на более, чем 16 цифровых сигналов. При этом максимальная частота сэмплирования составит 100MHz (количество используемых входов можно выбрать программно, при этом выбирается и широкий ряд значений до максимально возможного для данной конфигурации).

Запустим ту же программу инициализации дисплея, но уже на 16-битной шине:

Инициализация LCD на 16-битной шине



Операции по записи в регистры LCD при его настройке по-прежнему выполняются в восьмибитном формате, 16 бит используются только при записи в графическую память, что видно в правой части экрана, после появления на шие команды начала записи в память (0х22). Это уже идет выполнение программы LCD_clear(uint16_t color), котрая заполняет весь экран, в данном случае, серым цветом (0х7BEF).

Ну и, напоследок, максимальное быстрое заполнение серым цветом экрана, которое у меня получилось на «чистом С»:


Запись константы в графическую память



Четыре с половиной миллиона 16-цветных точек в секунду, при размерах дисплея 320х240, дают более 59 кадров в секунду. Как показано выше, ассемблер даст возможность серьезно улучшить и этот результат.

Разумеется, был запущен тест из предыдущей заметки, с мультиком и Штирлицем. 8-битный режим уехал за 20 фпс и уперся с производительность дисковой подсистемы. Суммарное время «рваного» чтения кадра, не влезающего в приемный буфер 12 килобайт - более 40мс, что ограничивает итоговый результат (без использования DMA), размер же 24-битного исходного кадра в три раза больше. Чтение 8-битных четвертинок со внешних флэшек, не обремененных файловой системой — 22мс. Но это тоже тема не сегодняшнего материала.


Кстати, может возникнуть вопрос, а можно ли подобными маневрами поднять фпс на обычном PC, работающем под DirectX? Можно, но на это уйдет вся жизнь. Ввиду сложности самой компоненты, необходимости пересоздания инклюдов, да и вся программа на ассемблере сведется к многочисленным invoke сишных функций API DirectX. При этом от классического ассемблера ничего не остается. Другое дело, когда ты с железом один на один без запутанной (часто намеренно) программной прослойки. Тут уже есть возможность выцарапать лишние миллисекунды.

Итог

Как в свое время и веллемановский осциллограф-генератор PCSGU-250, OLS кажется тем прибором, который, надеюсь, на достаточно долгое время, закроет мои текущие нужды по контролю за тем, что творится на цифровых линиях моих игрушек. Конечно, это не DSO-модули к многокилобаксовым осциллоскопам, но и стоит он всего менее 50 долларов ( с доставкой!).
Девайс из серии мust have. А когда еще и несколько проколов из клиента уберется, то все будет в полном ажуре.

Оформленные словами мысли по поводу вышеизложенного — сюда.

На сегодня все,
Zauropod,
5 декабря 2010 года.
Оценитe материал

Возможно вас заинтересует

Популярные новости

Сейчас обсуждают