В комментариях к статье про управление RGB светодиодами средствами блока UDB микроконтроллеров PSoC фирмы Cypress было высказано мнение, что неплохо бы в начале статьи кратко рассказать, что такое вообще UDB. Однако про UDB кратко не написать, но можно перевести фирменную документацию, чтобы познакомить отечественного читателя со столь мощным средством для реализации микропрограммных функций.
Но прежде, давайте рассмотрим, что вообще такое PSoC. PSoC — это набор семейств микросхем фирмы Cypress для реализации систем на кристалле. Разные семейства имеют разное процессорное ядро (для PSoC 3 это MCS-51, для PSoC 4 — Cortex M0, для PSoC 5LP — Cortex M3, а для PSoC 6 — сразу два: Cortex M0+ и Cortex M4) и набор программируемой логики. Причём логика эта не чисто цифровая, есть там и аналоговые вещи. Кроме набора различных АЦП, там присутствуют также аналоговые коммутаторы. Можно даже программно связывать ножки через аналоговые цепи, правда, сопротивление у цепи будет измеряться килоомами. Есть внутри PSoC и операционные усилители, которые можно программно коммутировать, а значит — строить на них разные аналоговые блоки.
Кстати, PSoC’и можно питать любым напряжением от 2.7 до 5.5 вольт. То есть не нужно думать о каких-то стабилизаторах ни при батарейном питании, ни при питании от USB.
Но про аналоговые вещи я написал чисто для красного словца. Сейчас мы сосредоточимся на вещах цифровых. В большинстве современных контроллеров имеются мощные периферийные блоки, которые предоставляют огромное множество функций. Но на практике, в каждой конкретной программной разработке эти блоки используются не полностью, а только частично. И в PSoC вместо кучи добра реализована программная логика, похожая на логику классических ПЛИС. Соответственно, на ней можно реализовать именно те блоки, которые нужны, включив их именно в те режимы, которые требуются. А на неиспользуемые режимы ресурсы не тратить, отдав их на реализацию каких-то собственных вещей.
И вот здесь часто возникает некоторое недопонимание. Многие разработчики привыкли к тому, что Программируемые Логические Интегральные Схемы (ПЛИС) бывают двух видов: CPLD и FPGA. Поэтому многие, кто слышал про PSoC, считают, что там кроется некая CPLD-шка, которую можно программировать на языке Veriolg. По факту — и да, и нет. Некоторое количество PLD (без «C», просто PLD) там действительно есть, и на Verilog их программировать действительно можно. Но реально, эти PLD входят в состав блоков UDB. И именно UDB является основным элементом программируемой логики, реализованной в PSoC. Этот блок чрезвычайно самобытен и предоставляет просто широчайшие возможности для разработчика. Рассмотрим рисунок из фирменной документации, поясняющий суть использования блоков UDB.
Так как я изучал всё на примере семейства PSoC 5LP, переводить буду документацию именно на него. Но перед тем, как начать, скажу пару слов про цену этих контроллеров. Если зайти на Ali Express и посмотреть на макетные платы для них, возникает грустное ощущение. Прямо скажем, по сравнению с STM32-DISCOVERY они ещё ничего, а вот на фоне макеток STM32F103C8T6 дороговаты. В первую очередь, это связано с тем, что на фирменных макетках всегда стоит не один, а два таких контроллера. Функции JTAG реализуются на PSoC 5LP, даже если целевой контроллер и PSoC 4 (у последнего обычно нет порта USB).
Но и поделив цену на два, всё равно получаем, что она выше, чем у сходного по процессорному ядру STM32F103. Тем не менее, если мы добавим к тому самому STM32 снаружи ещё и даже самую простенькую CPLD, то суммарная цена уже выйдет в пользу PSoC. А ещё добавим потерянные ножки на связь этих двух корпусов (у PSoC же все связи внутри). А ещё цену квадратных сантиметров платы. Вот и получается, что, если нужно работать только с процессорным ядром, в PSoC действительно нет необходимости. Если же нужно какой-то функционал вынести на микропрограммный или аппаратный уровень — тут нужен именно PSoC. На нём система выйдет дешевле и проще.
На самом деле, у меня есть маниакальная идея попробовать сделать аппаратную поддержку ядра нашей ОСРВ МАКС. Для этого я изучил методику разработки Bare Metal приложений под Altera V SoC (увы, выяснилось, что особенность архитектуры там такая, что ОС можно замедлить, но нельзя ускорить — одиночные запросы к аппаратуре там идут с бешеной латентностью). Для этого же я начал осваивать и PSoC. До разгона ядра ещё не дошёл (есть только общие мысли), но сама идея программирования UDB мне жутко понравилась. Само собой, я теперь заинтересован в том, чтобы донести эту идею до максимального числа отечественных программистов. Поэтому приступаем к переводу соответствующей части фирменной документации Cypress, посвященной UDB. Нумерацию глав и рисунков сохраняем в соответствии с оригинальным документом.
В этой главе мы рассмотрим, как универсальные цифровые блоки (англ. Universal Digital Blocks, UDB) позволяют разрабатывать программируемые цифровые периферийные функции. Архитектура UDB обеспечивает баланс между гранулярностью конфигурации и эффективной реализацией. UDB состоят из комбинации нескоммутированной логики, схожей с программируемой логической матрицей (ПЛМ, англ. PLD), структурированной логики (операционные автоматы, далее — Datapath) и гибкой схемы трассировки.
Рисунок 21-1 показывает UDB в виде конструкции, содержащей два базовых логических блока PLD, Datapath и функции управления, статуса, тактирования и сброса.
Рисунок 21-1. Блок схема UDB.
В каждом UDB есть две PLD «12С4». Блоки PLD, показанные на рисунке 21-1, можно использовать для реализации конечных автоматов, обработки данных ввода/вывода и для создания табличной логики (англ. Lookup Table, LUT). Кроме того, PLD можно настроить для выполнения арифметических функций, установки последовательности Datapath и генерации статуса. Общая логика может быть синтезирована и спроецирована на блоки PLD. Этот раздел содержит обзор архитектуры PLD.
PLD имеет 12 входов, которые передают информацию на 8 конъюнктивных термов в массиве AND. В каждом конъюнктивном терме можно выбрать прямой (true, Т) или инверсный (complement, С) вход. Выход конъюнктивных термов идет на вход массива OR. Буква ‘C’ в 12С4 показывает, что термы OR постоянны для всех входов, а каждый вход OR может получить программный доступ к любому конъюнктивному терму. Такая структура обеспечивает максимальную гибкость и гарантирует, что все входы и выходы могут быть перемещены.
Рисунок 21-2. Структура PLD 12С4.
Архитектура макроячеек показана на рисунке 21-3. Выход управляет трассировочным массивом и может быть защелкнут или комбинаторным. Для защелкивания используется D-триггер с прямым или инверсным входом либо T-триггер с высоким или низким входным уровнем. Выходной триггер может быть установлен или сброшен при инициализации или асинхронно при нормальной работе, по внешнему сигналу из трассировочного канала.
Помимо управления трассировочным массивом, выходы макроячеек обеих PLD спроецированы на адресное пространство в виде 8-битного регистра «только для чтения», доступ к которому можно получить при помощи CPU или DMA.
Рисунок 21-4. Регистр макроячейки PLD «только для чтения».
PLD связаны вместе в адресации UDB. Как показано на рисунке 21-5, вход цепи переносов «selin» пробрасывается из предыдущего UDB в цепи, через каждую макроячейку в обеих PLD, после этого направляется на следующий UDB в виде выхода цепи переносов «selout». Для поддержки эффективного размещения арифметических функций, генерируются специальные конъюнктивные термы (PT), которые используются в макроячейках совместно с цепочкой переносов.
Рисунок 21-5. Цепь переносов PLD и входы специальных конъюнктивных термов.