Как считать программу с микроконтроллера
Ответы на часто задаваемые вопросы:
1. Для кого предназначен этот FAQ?
Большинство специалистов разрабатывающие устройства на микроконтроллерах уже знакомы с темой защиты программ микроконтроллеров, поэтому можно считать, что данный раздел им ни о чем новом не расскажет. Однако имеется огромная армия инженеров и простых потребителей электронных устройств не знакомых с детальной организацией подобной защиты, но желающих либо разобраться в деталях работы имеющегося устройства, либо создать подобное устройство, для них то и предназначен этот сборник ответов на вопросы.
2. Для чего и от кого делается защита микроконтроллеров?
Многие производители электронных устройств стараются защитить свое устройство от возможности простого копирования его другим производителем. Им навстречу пошли производители микроконтроллеров, введя в функционал своих изделий защиту от копирования программы (микропрограммы) содержащийся в памяти микроконтроллера. Используя эту защиту от чтения микропрограммы (прошивки) производители электронных устройств могут защитить свой продукт от простого копирования другим производителем.
3. Что представляет собой защита от копирования в микроконтроллере, и почему я сам не могу считать защищенную микропрограмму (прошивку)?
Обычно защита от копирования устанавливается во время программирования микроконтроллера путем установки специального бита защиты или нескольких бит в слове конфигурации микроконтроллера. Физически эти биты располагаются в специальных ячейках памяти на кристалле микроконтроллера. Иногда используются другие методы защиты, например защита паролем, но принцип сохраняется. Чтобы снять защиту обычно необходимо изменить значение этого бита или нескольких битов, хотя часто могут использоваться и другие методы считывания содержимого памяти программы микроконтроллера. Обычными методами, например программатором, это сделать не удастся, необходимо сложное дорогостоящее оборудования, которого обычный разработчик электронных устройств не имеет. Поэтому мы, имея необходимое оборудование, знания и опыт, специализируемся на предоставлении подобного рода услуг.
4. Что дает мне снятие защиты от чтения микропрограммы (прошивки)?
Допустим, у Вас есть устройство, которое Вы приобрели у одного из производителей электронных устройств и Вы хотите производить такое же, но модифицированное устройство. Но исходников микропрограммы или готовой прошивки у Вас естественно нет, и Вам будет необходимо полностью с нуля разрабатывать и отлаживать микропрограмму. На это, по сравнению с копированием электронной составляющей устройства (схемы), придется потратить много денег и времени. Пользуясь нашими профессиональными услугами, Вы сэкономите и деньги и время на разработку устройства. При наличии устройства или его электрической схемы мы можем восстановить полностью алгоритм его работы и текст микропрограммы на языке программирования Си или Ассемблер.
5. Какова законность таких действий с точки зрения законодательства?
Все микропрограммы (прошивки) мы считываем по заказу клиента с целью ремонта его устройства, либо для ознакомления с алгоритмом работы микропрограммы. Вся дальнейшая ответственность за незаконное распространение микропрограммы или иные действия с ней или с её помощью ложится полностью на заказчика.
Наша компания работает на территории РФ, поэтому ниже приведем цитату из закона. Законодательство других стран декларирует аналогичную позицию.
Статья 1280 ГК РФ. «Свободное воспроизведение программ для ЭВМ и баз данных. Декомпилирование программ для ЭВМ».
2. Лицо, правомерно владеющее экземпляром программы для ЭВМ, вправе без согласия правообладателя и без выплаты дополнительного вознаграждения изучать, исследовать или испытывать функционирование такой программы в целях определения идей и принципов, лежащих в основе любого элемента программы для ЭВМ, путем осуществления действий, предусмотренных подпунктом 1 пункта 1 настоящей статьи.
3. Лицо, правомерно владеющее экземпляром программы для ЭВМ, вправе без согласия правообладателя и без выплаты дополнительного вознаграждения воспроизвести и преобразовать объектный код в исходный текст (декомпилировать программу для ЭВМ) или поручить иным лицам осуществить эти действия, если они необходимы для достижения способности к взаимодействию независимо разработанной этим лицом программы для ЭВМ с другими программами, которые могут взаимодействовать с декомпилируемой программой.
6. Что представляет собой дополнительная защита от чтения и почему она лучше обычной?
Дополнительная трёхуровневая защита предназначена для создания условий невозможности чтения микропрограммы (прошивки) известными методами. Она может включать в себя от одного до трёх уровней защиты: защита от вскрытия корпуса, скрытый внутрикорпусной обрыв ножки используемой программатором для чтения, скрытое внутрикристальное удаление логики управления ножкой используемой для чтения.
Первый уровень представляет собой стойкий к кислотам и растворителям тугоплавкий полимер, что не позволяет добраться до кристалла.
Второй уровень делает невозможной процедуру считывания программатором без специальных дорогостоящих инструментов.
Третий уровень выполняет аналогичную второму функцию, но при этом внутрикристальное восстановление логики управления на внутренних слоях практически не возможно, либо требует очень дорогостоящего оборудования.
Учитывая, что в подавляющем большинстве случаев обычная заводская защита легко обходится, дополнительная защита для многих дорогостоящих и сложных устройств является крайне необходимой мерой для предотвращения материальных потерь связанных с попаданием плодов интеллектуальной деятельности в руки третьих лиц.
7. Я хочу установить дополнительную защиту, но я боюсь, что вы считаете мою суперсекретную программу перед установкой защиты. Есть ли какой-то способ установить дополнительную защиту на микросхему, перед тем как я ее окончательно запрограммирую?
В данном случае перед установкой нашей дополнительной защиты можно прошить только бутлоадер без основной программы. После того, как мы установим дополнительную защиту, вы уже сможете запрограммировать основную память. Причем бутлоадер для загрузки основной программы должен использовать любой другой интерфейс отличный от основного, использующегося для стандартного программирования, так как основной интерфейс будет отключен после установки нашей дополнительной защиты. Обычно сам бутлоадер не представляет никакого интереса для копирования. В качестве бутлоадера можно использовать свой, либо модифицированный из примеров от производителя микроконтроллера.
8. Я боюсь, что после считывания моя программа может быть передана или использована третьими лицами.
Это исключено, мы никогда никому не передаем считанные микропрограммы и восстановленные исходники, не храним и не используем их сами в своих целях.
9. Работаете ли вы с юридическими лицами?
Да, мы работаем с юридическими лицами в качестве самозанятого (НПД). Выдаем чек от самозанятого после оплаты. Другие документы нам не нужны. Если нужно, есть пример договора и акта: договор, акт
Как считать программу с микроконтроллера
_________________
Создать электронный мир проще,чем его понять.
_________________
Кто не пил ни разу водки-тот не знает вкус воды!
А проверить это можно я так понимаю тупо прочитав микроконтроллер?
_________________
Создать электронный мир проще,чем его понять.
Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет
Попробывал скопировать прошивку с набора МастерКИТ не получается,наверно они знают о защитных фьюзах.Мало того что у них цены космические,так они и схемы,и печатки и прошивки скрывают зла не хватает !
_________________
Создать электронный мир проще,чем его понять.
_________________
Создать электронный мир проще,чем его понять.
технология простая: сначала учишься на хорошо и отлично, потом работаешь, набираешься опыта, потом где-то берешь хорошие приборы, чтобы снять сигналы. на основе этого долго-долго думаешь и разрабатываешь полный функциональный аналог
_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется.
скушно, бабоньки!
_________________
— Если вы такие умные, то почему тогда строем не ходите?
ἓν οἶδα ὅτι οὐδὲν οἶδα (с) Σωκράτης
технология простая: сначала учишься на хорошо и отлично, потом работаешь, набираешься опыта, потом где-то берешь хорошие приборы, чтобы снять сигналы. на основе этого долго-долго думаешь и разрабатываешь полный функциональный аналог
Часовой пояс: UTC + 3 часа
Кто сейчас на форуме
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5
0. Перед прочтением статьи

Всё собиралось на виртуальной машине Windows XP Professional 2002 SP3, запущенной через VirtualBox версии 5.2.22r126460 на хосте Windows X.
1. Установка драйвера для переходника USB-COM
Windows не в помощь, качаем с оф.сайта Prolific (первая ссылка на запрос «prolific driver» в Гугле) драйвер USB to UART/Serial/Printer PL2303 Windows Driver (нужен тот, который Standard Driver). Либо можете скачать с моего облака.
Устанавливаем драйвер, перезагружаемся и видим новый COM-порт.

Настройки порта оставил стандартные. Можете изменить номер COM-порта на своё усмотрение. На своём опыте только один раз в жизни видел, чтобы программа видела только первые 4 COM-порта, если не ошибаюсь это был какой-то Bluetooth-терминал под Windows.
2. Заливка прошивки на плату и с платы
2.0 Скачивание утилиты для работы с платой
Качаем с оф.сайта STM утилитку FLASHER-STM32 (в описании зовётся STM32 Flash loader demonstrator (UM0462)), для этого придётся зарегистрироваться, но это не страшно — в итоге нам упадёт zip-архив с установочником; Next->Next->Next… и всё установлено. Я для удобства в рабочей папке создаю ярлык на это приложение.
По умолчанию путь к утилите C:Program Files\STMicroelectronics\Software\Flash Loader Demo\STMFlashLoader Demo.exe.
2.1 BOOT-нюанс
На плате имеется перемычка (джампер) BOOT.
- Когда перемычка замкнута, микроконтроллер будет загружать инструкции из своей памяти (т.е. программу, написанную программистом).
- Когда перемычка разомкнута, микроконтроллер будет принимать информацию по линиям RX и TX, т.е. будет прошиваться от COM-порта (от переходника в моём случае).
2.2 Настройка утилиты

Запустим это приложение, оно на самом деле наипростейшее (содержит минимум настроек). На первом окне выбираем:
- интерфейс (у меня это COM-3);
- скорость, с которой будет общаться компьютер и микроконтроллер (имхо, 9600 нормальное значение);
- количество бит данных (у меня это окно почему-то недоступно, но пока это не важно);
- чётность (у меня без чётности, т.е. None);
- echo (у меня ВЫКЛ);
- время ожидания (у меня 10 секунд).
Порядок шагов, которые помогают всегда:
- Во-первых, нужно проверить не замкнута ли перемычка BOOT на плате.
- Во-вторых, в любом случае, отключить питание микроконтроллера и желательно линии TX и RX, идущие от переходника на плату (землю можно не отключать).
- В-третьих, в программе прожать Back до конца, т.е. до первой странички, или же вообще закрыть её и запустить заново (вообще говоря, она иногда подвисает). Важно перед каждым подключением к плате через эту программу всегда начинать с первой страницы.
- В-четвёртых, подцепить обратно провода от переходника к плате и снова попытаться подключиться в программе (обязательно с первой странички!).
Т.к. я работаю через виртуальную машину, приходится по несколько раз переподключать переходник USB-COM, чтобы он был обнаружен виртуальной машиной, а хост-машина не успела установить нерабочие драйвера.
Другой вариант, который я обнаружил рабочим во время написания этой статьи — это нажатие кнопки на плате вместо постоянного дёргания проводов. Однако замыкать и размыкать перемычку BOOT придётся в любом случае. Работает этот вариант, потому что кнопка подведена к ноге внешнего сброса NRST .
На следующем окне нужно выбрать целевое устройство Target. Кстати говоря, иногда здесь можно увидеть (возможно, это баг) вообще левое устройство, например вместо STM32 увидеть STM8 — где-то произошёл какой-то сбой, порядок лечения описан выше. Поэтому на этом шаге нельзя спешить жать Next, а всегда обращать внимание на то, что в Target выбрано нужное устройство.
Как определить, какое у нас устройство? — смотрим на чип и переписываем себе всё, что на нём написано. Открываем Datasheet на наш чип, в разделе Ordering information описано, какая буква за что отвечает. В моём случае это:


Предлагается на выбор 4 действия с чипом:
- стереть память (всю или выбрать конкретную область);
- записать прошивку на устройство;
- считать прошивку с устройства;
- включить/отключить защиту от записи или чтения.
2.3 Считывание прошивки с платы
При самом первом моём подключении платы я решил сохранить исходную прошивку, этакий бэкап — сделаем это и сейчас. Нужно будет указать, куда сохранять эту прошивку и какие страницы памяти сохранять, также на выбор предлагается использовать hex, bin или s19 формат файла.
Если только заливать на плату или считывать с платы прошивку, то разницы между этими форматами файлов никакой нет. Далее следует страница прогресса, на которой у меня иногда надолго подвисает процесс на 99% (не обязательно именно 99), но спустя несколько секунд якобы успешно завершается — на самом деле после этого плата не выдавала то поведение, которое соответствовало бы загружаемой прошивке. Проще говоря, надо всё переподключить и заново залить прошивку, ничего критичного в этом нету.
Файл прошивки сохранился, и в будущем его можно заливать на плату.
Однако, если установлена защита от чтения, считать прошивку не получится.
2.4 Прошивание платы
Сейчас зальём файл прошивки, написание исходного кода которой приведено ниже. Забегая вперёд скажу, что заливать будем bin и hex файлы, т.к. именно их будет выдавать среда разработки. Дополнительные настройки для s19 и hex файлов идентичны; в отличие от них у bin файла можно выбрать адрес, с которого будет записываться прошивка, по умолчанию в утилите он равен 8000000 (нам подходит).
Перед записью можно очистить Flash память микроконтроллера, выбрав один из трёх вариантов:
- Erase necessary pages (очистить необходимые участки памяти);
- No Erase (без очистки);
- Global Erase (полная очистка).
Ещё есть опциональные байты, но пока их можно не трогать. Жмём Next, ждём завершения процесса и всё готово.
На случай, если хотите записать мою прошивку, найти её можно в облаке, файл blink.bin. При использовании данной прошивки должен мигать встроенный светодиод, запитанный от ножки PA4.
3. Написание кода
3.0 Установка среды разработки CooCox CoIDE
Скачать IDE можно с сайта SoftPedia.com, раньше можно было скачать с сайта STM и с сайта самой IDE, но с тех пор, как IDE перестали поддерживать, это стало невозможным. Ничего критичного в том, что IDE перестали поддерживать, нету, т.к. для написания кода главное — это компилятор. Я скачал обе версии, но пользуюсь версией 1.7.8.
Первый запуск среды хорошо описан здесь, Next->Next->Next… и ничего сложного. Добавлю только, что сначала лучше создавать проект, а потом всё остальное.
И ещё, если потеряли вкладку Repository, найти её можно в меню View -> Repository.
Скачать инструменты (компилятор) для среды можно тут или спросить у Гугла «gnu tools for arm»; я скачивал вариант, у которого на конце sha1.exe.
3.1 Каркас исходников
Итак, проект создан, чип выбран, теперь добавим в проект минимальный набор исходников, без которых он вообще не сможет жить.
Выделим CMSIS BOOT и среда автоматически выделит M0 Cmsis Core, т.к. зависимости требуют этого.
Соберём проект (значок Build, или клавиша F7). По непонятным мне причинам hex файл не собрался (в консоли есть предупреждение); я несколько раз переустанавливал IDE и компилятор, заново создавал проект, но на виртуальной машине почему-то такой результат; на другом компьютере (не виртуальном, а реальном) всё один-в-один и на выходе рабочий hex. К счастью, есть bin.
Хоть код и ничего не делает, я заливаю его на плату, дабы убедиться, что залить можно (что, например, утилита его не отбраковывает). Советую сделать это и читателю. Если не получается — попробовать ещё и ещё раз, а также писать комментарии.
3.2 Алгоритм на пальцах
Для начала набросаем алгоритм, как с точки зрения человека микроконтроллер будет мигать светодиодом. А для этого немного рассуждений.
Каждая техника работает за счёт запасённой энергии, например некоторые двигатели могут работать на разных видах топлива, но для этого двигатель нужно скорректировать под вид топлива, которым мы собираемся его кормить. Аналогично и микроконтроллер требуется скорректировать (настроить) под источник энергии — это будет первый блок алгоритма.
Рассуждаем далее. У настольного компьютера есть монитор, колонки, клавиатура, мышь… и можно заметить, что некоторые устройства предоставляют нам информацию, а с помощью других мы предоставляем информацию компьютеру, но все они подключены к общей для всех них коробке (системному блоку). Можно догадаться, что и микроконтроллер может получать и отдавать информацию, а это значит, что его ножки могут принимать сигнал или выдавать сигнал — это будет следующий блок алгоритма.
Далее микроконтроллер должен включать светодиод, ждать какое-то время, выключать светодиод, ждать какое-то время и заново включать-ждать-выключать…
В итоге алгоритм будет выглядеть примерно так

Назначение данной блок-схемы — наглядно показать, что делает алгоритм; в первую очередь схема пишется для себя, поэтому каждый волен писать\рисовать её как хочет (для себя). Я считаю, что схема должна преследовать цель быть максимально простой, удобочитаемой и наглядной, иметь высокий уровень абстракции.
В соответствии с этим алгоритмом будем писать код.
3.3 Работа с документацией
Данную часть статьи рекомендую читать с открытым файлом stm32f0xx.h, который лежит в папке cmsis_boot нашего проекта, и открытой документацией.
3.3.1 Выбор источника тактирования
Во-первых, нужно обеспечить питание микроконтроллера. Микроконтроллер получает от переходника 5 Вольт (замерял мультиметром), однако возникает вопрос «на какой частоте работает микроконтроллер», ведь известно, что электроника работает на разных частотах. Сперва откроем datasheet, в содержании можно увидеть два раздела, подходящие по смыслу: Power management, Clocks and startup. В первом идёт речь о вольтаже и о режимах низкого энергопотребления. Во втором разделе прячется то, что нам интересно в данный момент. Уже в самом первом предложении сказано «the internal RC 8 MHz oscillator is selected as default CPU clock on reset», что значит, что по умолчанию после сброса МК в качестве основного источника тактирования выбирается внутренняя 8-ми МГц RC-цепочка.
Далее идёт какая-то непонятная схема Clock tree, которую мы рассмотрим чуть позже.

Строго говоря, можно положиться на фразу «по умолчанию после сброса МК. » и прочитать по диагонали данную часть статьи.
Сейчас нужно отвлечься на плату и поискать внутренний светодиод. Мне известно, что диоды на схемах обозначаются D1, D2. т.е. D == diode, на моей плате недалеко от резистора R7 находится диод D1.
Возможно, внимательно рассмотрев плату вы сможете проследить, к какой ножке подцеплен диод, я же обращусь к схеме платы. К сожалению, элементы платы не в точности соответствуют элементам на схеме по своему расположению; но я рад, что нашёл такую схему в интернете (а то вообще долго не мог найти ничего).

На схеме видим, что катод диода через перемычку J2 подцеплен к земле, а анод через резистор подцеплен к выводу PA4. PA4 означает 4-ый вывод порта A, а это значит, что для зажигания и отключения светодиода надо будет подавать напряжение на вывод PA4.
Далее нужно определить, каким образом подать напряжение на этот вывод. Для меня это было вовсе не интуитивно, и я долго бороздил документацию вдоль и поперёк, пока не наткнулся в самом начале даташита на схему Block diagram в разделе Description. И в ней я увидел заветную дорожку PA[15:0] <=> GPIO port A <=> AHB decoder <=> Bus matrix <=> Cortex-M0, т.е. порт А является портом ввода-вывода общего назначения и подключен к шине AHB .
(Картинка кликабельна)
Отмечу, что в электронике принято разбивать выводы микроконтроллера на порты, и обычно у порта имеется 16 выводов. На диаграмме видно, что у портов A, B и C их как раз 16, а вот у портов D и F их меньше (меньше 16-ти выводов может быть, больше — нет).
Вернёмся к схеме Clock tree и найдём вывод, подписанный AHB. Разберёмся, на какой частоте работает данный вывод. К AHB идёт сигнал HCLK, который выходит из делителя HPRE. На этот делитель поступает сигнал SYSCLK с переключателя SW . Программно задаётся то, какой из сигналов на входе SW будет использоваться в качестве SYSCLK — далее мы это зададим в коде. На выбор предлагается:
Перейдём в Reference manual и откроем раздел 7 Reset and clock control (RCC), а конкретно 7.2.6 System clock selection, где ещё раз натыкаемся на похожую формулировку, встретившуюся в даташите: «after a system reset, the HSI oscillator is selected as system clock» — т.е. нам даже ничего делать не надо, МК сам заведётся на HSI.
Чтобы убедиться, что МК действительно будет работать от этого источника, я пропишу это явно в программе; пролистываем до регистров, которые отвечают за сброс и тактирование (раздел 7.4 RCC registers). Первый регистр, описываемый в документации, это Clock control register (RCC_CR); ниже идёт описание битов, какой за что отвечает.
Нас интересует нулевой бит HSION, который отвечает за включение резонатора (0 — выключен, 1 — включен).
Таким образом, необходимо будет записать единицу в регистр RCC_CR. (нулевой бит это единица, или 2 0 = 1).
Теперь найдём в файле stm32f0xx.h определение RCC (#define RCC).
Как видим, это структура, расположенная по адресу RCC_BASE; адрес 0x40021000, если развернуть все define, тот же самый адрес можно увидеть в Reference manual в разделе 2.2.2 Memory map and register boundary adresses и в даташите в разделе 5 Memory mapping (область AHB).
Чтобы записать в регистр CR блока RCC единицу для включения HSI, понадобится строка кода
3.3.2 Настройка ножек
Подача сигнала на ножку микроконтроллера для зажигания светодиода и прекращение подачи сигнала для того, чтобы светодиод потух, являются простыми действиями, а потому это относится к функциям GPIO (порты ввода-вывода общего назначения).
По умолчанию ножки МК не подключены, т.е. на выходе неопределённость. Необходимо подключить порт, ножка которого будет питать светодиод. Ранее мы определили, что порты GPIO подключены к шине AHB — нужно затактировать эту шину. Продолжая листать раздел 7.4 RCC registers (регистры управления сброса и контроля), встречаем раздел 7.4.6 AHB peripheral clock enable register (RCC_AHBENR, регистр включения тактирования шины AHB). Ранее я определил, что мой светодиод подключен к ножке PA4 — соответственно мне нужно записать единицу в 17-ый бит регистра, чтобы затактировать порт A.
Соответственно код должен быть
или, что то же самое,
либо используя #define файла stm32f0xx.h написать
Порт A мы запитали, теперь надо сообщить МК, что PA4 будет работать на выход — будем читать раздел 8 General-purpose I/Os (GPIO); во введении раздела уже сказано «Each general-purpose I/O port has four 32-bit configuration registers (GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR and GPIOx_PUPDR), two 32-bit data registers (GPIOx_IDR and GPIOx_ODR). » — у каждого GPIO порта есть 4 настроечных регистра и 2 регистра данных — это то, что нам надо (сконфигурировать порт A, а точнее вывод PA4, и периодически отправлять на него 0 и 1). Для лучшего понимания (теории) происходящего можно почитать данный раздел, я же пролистаю до раздела 8.4 GPIO registers и сконфигурирую порт в соответствии с описаниями.
-
режим порта — выход. В соответствии с документацией необходимо записать 01 в соответствующую область (MODER4) соответствующего регистра (GPIOA_MODER), т.е. биты 9 и 8: в 9-ом бите должен оказаться ноль, в 8-ом единица:
Следуя документации, необходимо записать ноль в 4-ый бит; также в документации указано, что после сброса здесь будет ноль.
Нужно подтянуть 4-ый вывод порта A; документация говорит, что для этого необходимо записать в 9 и 8 биты ноль и единицу соответственно.
3.3.3 Включение-выключение светодиода и задержка
По документации видим, что для каждого порта (A, B, C, D, F) есть 32-битный регистр, однако т.к. у порта не может быть более 16 выводов, то используются только первые 16 бит регистра. Каждый бит соответствует номеру порта (выводу). Для вывода единицы на ножку PA4 нужно записать единицу в 4-ый бит, для вывода нолика — записать ноль в 4-ый бит, т.е. убрать напряжение с вывода.

Код для включения светодиода будет выглядеть так
Код для выключения светодиода
Но если написать строку выключения светодиода вслед за строкой включения, то мигать светодиод не будет (если интересно, что произойдёт — можете попробовать; ничего не сгорит, это уже обговаривали выше) — значит нужно сделать задержку. Для задержки используются таймеры, но таймеры достойны отдельной статьи (ввиду сложности), поэтому мы сделаем костыльную задержку: будем гонять холостой цикл. Есть один момент: если включена оптимизация компилятора, то компилятор вырежет наш холостой цикл, и задержки не будет. Убедимся, что оптимизация не включена. Для этого зайдём в конфигурацию проекта (правой кнопкой на имя проекта в дереве проекта) и во вкладке Compile проверим строку Compile Control String: в ней должен быть аргумент -O0 («о ноль» значит, что оптимизация отключена). Если вы собирали всё по моей инструкции, то скорее всего у вас тоже будет -O0, т.к. так было по умолчанию и я здесь ничего не трогал. Аргументы -O1 -O2 -O3 означают что включена оптимизация соответствующего уровня.
Холостой цикл можно написать так:
Значение t я задал таковым неслучайно, рассуждал так: если микроконтроллер будет работать на 8MHz, то за секунду он выполнит предположительно 8000000 инструкций, если глубоко утрировать, то для полсекундной задержки понадобится прогнать цикл 4000000 раз.
Холостой цикл нужно будет прогонять и после включения светодиода, и после выключения, и всё вместе это зациклить.
3.4 Написание кода и запуск
Соберём вместе все строки кода, что мы до этого писали. Также надо подключить заголовочный файл stm32f0xx.h, т.к. мы опирались на него и брали из него определения структур, адресов и значений. В итоге должно получиться:
Жмём Rebuild и заливаем код на плату через утилиту.

Чтобы плата запустила новую прошивку, не забудьте замкнуть перемычку BOOT и сделать сброс (RESET).
4. Заключение
Код написан, всё работает. Сил потрачено немерено. Радует, что опираясь на документацию, получилось написать рабочий код, во многом благодаря тому, что у STM качественная документация.
В планах написать статью, как всё собрать руками, без IDE, через консоль, true oldschool, в идеале так, чтобы всё это делать из-под Linux. Сейчас работаю над ШИМ и АЦП (тоже на данной плате) — по ним тоже напишу статью.
USBasp | AVRDUDE | Программирование микроконтроллеров AVR

Чтобы перенести нашу программу с компьютера в микроконтроллер нам понадобится программатор USBasp и программа AVRDUDE. Сегодня существует широкий выбор программаторов, предназначенных для программирования микроконтроллеров AVR. Среди них можно найти много самодельных, который даже трудно назвать программаторами, поскольку они с помощью всего лишь нескольких резисторов напрямую подключаются к COM порту. Однако современные компьютеры и ноутбуки уже практически не оборудываются COM портами, поэтому одним из основных критериев при выборе программатора является возможность подключения его к USB порту. Наиболее дешевый, простой и очень распространенный – это программатор USBasp. Его можно приобрести практически в любом радиомагазине по доступной цене. Стоимость его в китайских интернет магазина находится в пределах от 1,5 $ до 3 $.
Программатор USBasp
Связь компьютера с микроконтроллером осуществляется посредством программатора USBasp через USB порт, а данные передаются по интерфейсу SPI – Serial Peripheral Interface (последовательный периферийный интерфейс). Для связи МК с программатором задействуются специальные выводы: MOSI, MISO, SCK, RESET, VCC, GND. Хотя SPI предполагает использование всего трех выводов MOSI, MISO и SCK, но мы будем задействовать все шесть выводов.

При обмене данными по интерфейсу SPI микроконтроллер может одновременно либо принимать (вывод MISO) либо передавать данные (вывод MOSI). Установка режима приема или передачи данных осуществляется путем подачи определенного импульса на вывод SCK.
Разъем программатора, как правило, имеет 10 пинов и подключается к микроконтроллеру с помощью 10 проводного шлейфа. Однако удобней пользоваться шлейфами, которые имеют переходник на 6 пин, так как в таком случае все пины заняты. У десяти пинового разъема одни пин остается не занятым, а четыре пина подключены к общему проводу (GND).


Для того, чтобы компьютер определил программатор необходимо установить драйвер USBasp.
Фото подсоединенного программатора к микроконтроллеру ATmega8 приведено ниже.

Единственный недостаток или, правильнее сказать, мелкое неудобство данного программатора заключается в том, что он не поддерживается (без различных ухищрений) Atmel Studio, поэтому приходится пользоваться сторонней программой. Наиболее зарекомендовавшей себя является AVRDUDE.
Настройка AVRDUDE
Теперь нам осталось выполнить финальный шаг. Запускаем программу AVRDUDE. По умолчанию открывается вкладка Program. В нижней части окна в меню Настройки выбираем тип программатора usbasp. Далее в категории Микроконтроллер выбираем наш микроконтроллер ATmega8. Ниже, в категории Flash кликаем по значку троеточия и в открывшемся меню указываем путь к скомпилированному файлу с расширением hex. Путь к файлу и сам файл будут теми же, что мы ранее задавали в Proteus.

Чтобы убедится в том, что программатор определен операционной системой (драйвер программатора корректно установлен) и правильно подключен к микроконтроллеру, кликаем по кнопке Чтение. Если ошибок нет, то появится окно с записью “Калибровочные ячейки генератора считаны!” И в верхнем окошке отобразится шестнадцатеричное число. У каждого МК это число индивидуальное.

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

Теперь кликаем по кнопке Программировать в категории Flash. При успешной записи программы в МК появляется окно с записью, приведенной ниже.

Результат записанной, или, как еще говорят, прошитой программы – это засветившийся светодиод, подключенный к выводу PC0 нашего микроконтроллера.

Первая наша программа очень проста, а частота работы микроконтроллера оставлена по умолчанию и для ATmega8 равна 1 МГц. В случае изменения частоты или подключения внешнего кварцевого резонатора, необходимо внести некоторые изменения во вкладке Fuses, путем установки галочек в соответственные чекбоксы CKSEL0… CKSEL3.

Подробно настройки данной вкладки мы рассмотрим в статье Fuses (биты настройки или биты защиты) микроконтроллера.