Тут велика різноманітність відповідей ... в основному це питання вирішується різними способами.
Я вже більше 25 років пишу вбудоване програмне забезпечення та програмне забезпечення низького рівня на різних мовах - переважно на C (але з переходами на Ada, Occam2, PL / M та безліч асемблерів).
Після тривалого роздуму, спроб і помилок я застосував метод, який отримує результати досить швидко і досить легко створити тестові обгортки та джгути (де вони додають значення!)
Метод виглядає приблизно так:
Напишіть код коду абстракції драйверів або апаратних засобів для кожної основної периферійної пристрої, яку ви хочете використовувати. Також напишіть один, щоб ініціалізувати процесор і налаштувати все (це створює сприятливе середовище). Зазвичай на невеликих вбудованих процесорах - наприклад, ваш AVR - може бути 10 - 20 таких блоків, і все це мало. Це можуть бути одиниці для ініціалізації, перетворення A / D в нерозміщені буфери пам’яті, побітовий вихід, кнопковий вхід (відключення не тільки відбирається), драйвери модуляції ширини імпульсу, UART / прості драйвери послідовного використання, переривання використання та невеликі буфери вводу / виводу. Можливо, ще кілька - наприклад, драйвери I2C або SPI для EEPROM, EPROM або інших пристроїв I2C / SPI.
Після цього для кожного блоку апаратної абстракції (HAL) / драйвера я пишу тестову програму. Це покладається на послідовний порт (UART) та процесор init - тому перша програма тестування використовує лише ці 2 одиниці і лише виконує деякі базові введення та виведення. Це дозволяє мені перевірити, що я можу запустити процесор, і що у мене є основна послідовна підтримка налагодження вводу / виводу. Після того, як це працює (і тільки тоді), я тоді розробляю інші програми тестування HAL, будуючи їх на основі відомих хороших підрозділів UART та INIT. Тож у мене можуть бути тестові програми для зчитування побітових входів і відображення їх у хорошій формі (шістнадцятковий, десятковий, будь-який інший) на моєму серійному терміналі налагодження. Потім я можу перейти до великих і складніших речей, таких як тестові програми EEPROM або EPROM - я змушую більшість цих меню керувати, щоб я міг вибрати тест для його запуску, запустити його і побачити результат. Я не можу це написати, але зазвичай я не
Після того, як у мене все HAL працює, я знаходжу спосіб отримати звичайний галочку таймера. Зазвичай це швидкість десь від 4 до 20 мс. Це повинно бути регулярним, генеруватися в перерві. Як це можна зробити, перекидання / переповнення лічильників - це зазвичай. Потім обробник переривання ВКАЗУЄ розмір байту "семафор". У цей момент ви також можете поспілкуватися з управлінням живленням, якщо вам потрібно. Ідея семафору полягає в тому, що якщо його значення> 0, потрібно запустити "основний цикл".
Виконавець виконує основний цикл. Він майже просто чекає, коли цей семафор стане не-0 (я абстрагую цю деталь подалі). На цьому етапі ви можете пограти з лічильниками для підрахунку цих кліщів (тому що ви знаєте кількість галочок), і таким чином ви можете встановити прапори, що показують, чи є поточний виконавчий галочок на інтервал 1 секунду, 1 хвилину та інші загальні інтервали можливо, захоче використовувати. Як тільки керівник дізнається, що семафор> 0, він виконує один прохід через кожну функцію "додаток" обробляє "оновлення".
Процеси застосування ефективно сидять поруч і регулярно запускаються галочкою "оновлення". Це лише функція, яку викликає виконавча влада. Це фактично багатозадачні завдання з дуже простим домашнім RTOS, який покладається на всі програми, що надходять, роблячи невелику роботу та виїжджаючи. Програми повинні підтримувати власні змінні стану і не можуть робити тривалі обчислення, оскільки не існує преференційної операційної системи, яка б надавала справедливості. ОБОВ'ЯЗКОВО час запуску програм (сукупно) повинен бути меншим, ніж основний період галочки.
Наведений вище підхід легко розширюється, тому ви можете додавати такі речі, як стеки зв'язку, які запускаються асинхронно, а повідомлення comms потім можуть бути доставлені додаткам (ви додаєте нову функцію до кожного, яка є "rx_message_handler", і ви пишете диспетчеру повідомлень, які цифри з якої програми відправити).
Цей підхід працює майже для будь-якої системи комунікацій, яку ви хочете назвати - вона може (і вже була зроблена) працює для багатьох фірмових систем, відкритих стандартних систем comms, вона працює навіть для стеків TCP / IP.
Він також має перевагу, будучи модульними елементами з чітко визначеними інтерфейсами. Ви можете витягувати шматки в будь-який час, замінюючи різні частини. У кожну точку шляху можна додати тестовий джгут або оброблювачі, які будуються на відомих хороших деталях нижнього шару (деталі нижче). Я виявив, що приблизно 30% до 50% дизайну можуть отримати користь від додавання спеціально написаних одиничних тестів, які зазвичай доволі легко додаються.
Я зробив це все на крок далі (ідею, яку я отримав від когось іншого, хто це зробив) і замінив шар HAL на еквівалент ПК. Наприклад, ви можете використовувати C / C ++ і winforms або подібне на ПК, і, записуючи код, Дбайливо ви можете емулювати кожен інтерфейс (наприклад, EEPROM = файл диска, прочитаний у пам'яті ПК), а потім запустити всю вбудовану програму на ПК. Можливість використовувати сприятливе середовище налагодження може заощадити величезну кількість часу та зусиль. Тільки справді великі проекти зазвичай можуть виправдати цю кількість зусиль.
Наведений вище опис - це щось не властиве тому, як я роблю речі на вбудованих платформах - я натрапив на численні комерційні організації, які роблять подібні. Спосіб його виконання, як правило, сильно відрізняється у здійсненні, але принципи часто набагато однакові.
Я сподіваюсь, що вищесказане додасть трохи смаку ... такий підхід працює для невеликих вбудованих систем, що працюють в кілька кБ, з агресивним керуванням батареями до монстрів 100 Кб і більше джерел ліній, які працюють постійно. Якщо ви запускаєте "вбудований" на великій ОС, на зразок Windows CE тощо, тоді все вищезазначене абсолютно не має значення. Але це все-таки НЕ РЕАЛЬНЕ вбудоване програмування.