Навіщо мова Verilog програмісту мікроконтролерів

мікроконтролерів

Кілька разів починав писати цю статтю та кидав. Кидав тому, що тема, як на мене, дещо спірна. Винайдений мною велосипед може комусь здатися смішним та безглуздим і взагалі не зовсім коректним. Проте…

Взагалі, мені здається, що в галузі розробки електронних пристроїв існує кілька мало пересічних світів. Наприклад, існує розробка пристроїв на базі мікроконтролерів і паралельно існує розробка пристроїв на базі ПЛІС. Принципи роботи цим мікросхем принципово відрізняються і так само відрізняються принципи та методи розробки, використовувані мови програмування та налагодження. Звичайно, вибір елементної бази залежить від поставленого завдання. Однак і так зрозуміло, що ці світи, світ мікроконтролерів та світ ПЛІС майже не перетинаються. Можливо, на стику технологій щось є?

Сам я, загалом, більше віддаю перевагу ПЛІС і навіть беру участь у блозі про ПЛІС, однак, нещодавно наша компанія взялася за розробку пристрою на базі мікроконтролера STM32. Власне основні проблеми, які ми зустріли, були не зовсім технічні, а скоріше організаційні.

Справа в тому, що незважаючи на укладений договір про розробку пристрою та незважаючи на наявність більш-менш узгодженого ТЗ на пристрій, так вийшло, що кожного тижня замовник приходив з новими ідеями, вимогами, думками та побажаннями. Можна було б звичайно, послати їх кудись подалі, але ми вирішили, що постараємося бути терплячими і все-таки виконуватимемо проект.

Найголовніша організаційна проблема – запитів, що надійшли, на зміну алгоритму управління контролера було дуже багато і часто вони були дуже суперечливі. Причому замовник сам не був упевнений, як воно має працювати і навіть не дуже розумів, як вінвсе це перевірятиме. Точніше сказати так. Є менеджери, які хочуть мати якийсь контролер у свій агрегат. Які функції мають бути у контролера і агрегату самі менеджери точно не знають і вимоги повинен був сформувати єдиний інженер, який і повинен був перевірити працездатність пристрою. Своєї методики перевірки працездатності контролера у інженера немає, тому що немає досвіду роботи з електронними пристроями.

Ось такий приклад. У режимі очікування, коли контролер просто чекає натискання кнопки «Пуск», наш контролер повинен раз на добу включати насос, що прокачує рідину, на 10 секунд. Це тип захисту від закисання сальників насоса. Коли я запитую; "Ви як будете цю функцію перевіряти" - відповідають, що "ніяк". Особисто я в шоці. Ми, звичайно, намагаємося писати програми «без помилок», але думаю сторона, що приймає, те саме якось повинна ділити відповідальність, проводити свої випробування і т.д.

Далі перейду власне до технічного боку справи.

Ми вирішили, що нам потрібні свої тести програмного забезпечення мікроконтролера.

Зазвичай у світі є таке поняття юніт-тестування. І в принципі, ця методика певною мірою підходить і для програм мікроконтролера. В даний час програми для мікроконтролерів часто пишуться звичайною мовою Сі, так що з юніт тестами, загалом, проблем бути не повинно. Хоча… не все можна легко перевірити юніт тестами у мікроконтролері.

Все що пов'язане з програмуванням внутрішніх апаратних пристроїв на кшталт таймерів, каналів DMA, послідовних портів, переривань тощо – з цим є проблеми. Тут для налагодження в пору купувати осцилограф і дивитися які сигнали мікроконтролера виходять на входах-виходах. І взагалі поміряти скільки часу йдеобробка переривання – справа не зайва. І це вірно.

Є ще один нюанс із юніт тестами. Як мені здається, звичайне юніт-тестування ПЗ орієнтоване на дані. Ну тобто зазвичай програма юніт-тест подає різні передбачувані дані на вхід функції, що перевіряється, і далі перевіряє, що оброблені вихідні дані відповідають вимогам. Всі.

Для електронного пристрою, який виступає як обробник вхідних сигналів, принципово важливе поняття «протягом часу». Ну тобто вимоги зазвичай такі: при виникненні позаштатної ситуації та спрацьовуванні аварійного датчикаAпослідовно з інтерваломN1секунд вимкнути виконавчі пристроїB,C, а пристрійDвимкнути не пізнішеN2секунд але не ранішеN3секунд, Щось подібне до цього.

Зрозуміло, що для перевірки алгоритму керування програмними засобами добре використати якийсь симулятор сигналів з урахуванням перебігу часу. І такі кошти є в арсеналі… розробники систем на ПЛІС.

Розробник електронних пристроїв на базі ПЛІС зазвичай використовує мову опису апаратури Verilog або VHDL. При цьому, крім коду для ПЛІС, пишуться так звані testbench – це і є щось на зразок unit-test для звичайного програміста на Сі.

Я використовую Verilog HDL. Програму тестбенч пише сам програміст і при цьому намагається симулювати всі можливі вхідні на мікросхему ПЛІС. Вихідні сигнали аналізуються самим тестбенчем і перевіряються відповідно до очікуваних. При цьому сам симулятор Verilog стежить за часом у системі.

Розглянемо простий і абстрактний приклад, що робить програміст ПЛІС. Наприклад, ось модуль, який описує простий двійковий лічильник з асинхронним скиданням(sample.v):

Думаю такий код зрозуміє будь-який програміст, який навіть не знає мови Verilog HDL. Є два вхідні сигналиresetіclk. І є вихідний чотирибітний сигнал [3:0] cnt. Завжди на фронті тактового сигналу значення в лічильнику збільшується. І завжди при появі одиниці наresetлічильник обнулюється.

Цей модуль синтезується, тобто його планується відкомпілювати та зашити в ПЛІС.

Тепер, наприклад, програміст хоче перевірити працездатність свого модуля. Він пише програму на Verilog, тестбенч, який імітуватиме вхідні сигнали для мікросхеми (testbench.v):

Цей модуль не синтезується, його не можна відкомпілювати та зашити в ПЛІС, але він потрібен для симуляції проекту. Зверніть увагу на рядки

Це тестбенч вставлений досліджуваний екземпляр модуля sample. Виходить ось так:

навіщо

Цілком можливо, що у нас є критерій працездатності проекту. Нам потрібно, щоб під час сигналуresetвихідні сигнали лічильника завжди були в нулі. Тобто ми можемо в тестбенчі визначити сигнал помилки:

Цей сигнал можна програмно моніторити або просто подивитися очима на вихідних часових діаграмах.

Я часто використовую простий вільний симулятор VerilogHDL IcarusVerilog. Його просто встановити та працювати з ним. Компілюю та запускаю симулятор:

навіщо

Мій тестбенч завдяки рядкам програми $dumpfile("waves.vcd"); та $dumpvars(0,testbench); створює файл із часовими діаграмами waves.vcd. І ці часові діаграми можна подивитися за допомогою іншого чудового вільного інструменту GtkWave:

програмісту

Таким чином, найпростіше, що може зробити програміст ПЛІС - це написати до тестованого модуля тестбенч і згенерувати файли вийшлитимчасових діаграм і розглядати їх, дивитися правильний відгук йде від ПЛІС.

Тепер розповім, як можна схожу технологію тестування застосувати до мікроконтролерів.

Якщо ще раз зверніть увагу на Verilog тестбенч, то помітите там деякі системні функції на кшталт $display(..).

Так ось. Виявляється, для симулятора Verilog HDL можна самому дописувати необхідні нам системні функції мовою Сі. А якщо з'являється місце для мови Сі, то з'являється місце, де код Verilog тестбенча може взаємодіяти з Сиш код для мікроконтролера.

Взагалі, інтерфейс симулятора Verilog до мови Сі називається Verilog Procedural Interface (VPI). Розповідати про нього можна довго, це велика тема. Можна більше почитати, наприклад, тут.

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

Припустимо, проект для мікроконтролера складається з файлів:

Обробники переривань від вхідних ліній мікроконтролера описані у файлі Interrupts.c. Вони являють собою щось на зразок цього:

Коли сигнал на вхідній лінії мікроконтролера змінюється, відбувається переривання, у ньому проводиться читання значення лінії і це значення передається функцією Algo_set_val() алгоритму обробки. Весь алгоритм керування описаний у файлі Algorithm.c.

Файл Algorithm.c одночасно бере участь у проекті для мікроконтролера та у проекті для VPI модуля Verilog.

Verilog

Принаймні на тимчасових діаграмах можна побачити, як віртуально вмикається насос на 10 секунд кожної доби.

Останній етап – перестаємокомпілювати модуль VPI для Verilog симулятора (фіолетовий блок) і починаємо компілювати проект мікроконтролера (помаранчевий блок).

Тепер функції алгоритму викликатимуться не з віртуальних впливів симулятора Verilog, а з фізичних переривань від вхідних ліній та таймерів.

Про всяк випадок ще раз зауважу, що за допомогою нашого Verilog тестбенчу ми звичайно не перевіряємо правильність програмування регістрів периферійних пристроїв на кшталт DMA або таймерів або GPIO. Ми тестуємо лише «алгоритм управління». На мій погляд, і це дуже і дуже важливо.

Ну ось якось так.

Хардкорна конфа за С++. Ми запрошуємо лише профі.