Программирование arm с нуля: ARM-ы для самых маленьких / Хабр

Содержание

Архитектура ARM. Введение. | Прикладное программирование с нуля.

Всем привет. В сегодняшней статье мы с Вами познакомимся с архитектурой ARMИ в последующих записях будем работать с данными микроконтроллерами, повышая производительность и функциональность проектов. Рассмотренные уже нами мк AVR, и задействованные в различных устройствах, например последний сопрягая ATmega8A с ОС Android, как USB-устройство, в дальнейших проектах будут использоваться как промежуточные звенья.

Что же такое ARM? Начнем с истории. Расшифровуется аббревиатура как Advanced RISC Machine — усовершенствованная RISC-машина, либо — AcornRISC Machine. Где Acorn — название объединенного предприятия, а  Advanced — отдельный процессорный бизнес. Acorn – переименованная фирма CPU, которая выпустила в 1979 году свой первый компьютер Acorn System 1, в этом же году и переименована. Формально фирма ARM Holdings была создана в 1990 году, а конкретнее — в тот момент, когда было подписано соглашение между тремя компаниями: Apple Computer, Acorn Computers и VLSI Technology. Более подробно об истории можно почитать в статье по следующей ссылке: https://xakep.ru/2014/10/04/arm-history/.

ARM  — семейство 32-битных и 64-битных микропроцессорных ядер, которые широко используются в потребительской электронике. Появилась при изучении документации проекта RISC. Официальный проект Acorn RISC Machine был начат в октябре 1983 года. И первый процессор ARM1 был произведен  26 апреля 1985 года. Через год появились серийные процессоры arm2. Далее было семейство ARM3. ARM6 в 1992 году. И так далее. Сама компания не производит микросхемы и на данный момент не производит процессоры. Основной бизнес это продажа лицензий. Например обладатели «архитектурную лицензию» имеют право разрабатывать собственные микропроцессорные ядра, реализующие инструкции ARM и использующие патенты ARM. А в 2016 году японская компания Softbank (третий по величине оператор Страны восходящего солнца) приобрела британскую компанию ARM за $32 млрд.

Если сравнивать ARM c х86 , то последняя позиционируется как обработчик ресурсоемких задач, а ткакже CISC (Complex Instruction Set Computing), т.е. реализованы инструкции на все случаи жизни, в отличии от, RISC — набором минимально необходимых для работы команд. Минусом х86 можна назвать энергоемкость, соответственно выделения большого количества теплоты ну и сложность команд. ARM — минимальное энергопотребление, низкая цена, и низкая производительность работы по сравнению с x86.  В последнее время грань между обоими архитектурами стирается. ARM процессоры становятся более производительными и быстрыми. В общем стоит отметить что эти две архитектуры представляют основной процент продаж на рынке.

Архитектура развивалась с течением времени, и начиная с ARMv7 были определены 3 профиля:
— ‘A’(application) — для устройств, требующих высокой производительности (смартфоны, планшеты)
 — ‘R’(real time) — для приложений, работающих в реальном времени,

 — ’M’(microcontroller) — для микроконтроллеров и недорогих встраиваемых устройств.
M-профиль (версии ARMv6-M и ARMv7-M, ядра Cortex-M), строго говоря, не относится к «настоящим» ARM-процессорам. Во-первых, он кардинальным образом отличается по системной архитектуре от всех прочих разработок фирмы ARM, а соответственно, на системном уровне несовместим ни с более ранними процессорами, ни с другими профилями 7-й версии архитектуры. Во-вторых, в этих кристаллах реализована только система команд Thumb (ARMv6-M, ядра Cortex-M0 и -M1) или Thumb-2 (ARMv7-M, все прочие ядра Cortex-M), а команды набора ARM не поддерживаются. Предназначена эта серия для использования в качестве микроконтроллеров малой и средней производительности. Благодаря низкой стоимости и энергопотреблению они могут успешно конкурировать с намного более слабыми по вычислительными возможностям 8- и 16-разрядными микроконтроллерами. Заметим, что принадлежность ядер Cortex-M0 и -M1 к 6-й версии архитектуры является чисто формальной. Всю интересующую документацию можна скачать на официальном сайте https://developer.arm.com/
Забегая на перед, мы с Вами будем работать с архитектурой ARMv7Е-M, ядро Cortex-M. В процессе работы с ним изучим все тонкости.
Ниже таблица семейства Cortex-M.

И последнее рассмотрим набор инструкций Thumb. Это режим процессоров ARM (начиная с ARM7TDMI), где используется сокращенная система команд. Состоит из 36 команд, взятых из стандартного набора 32-разрядных команд архитектуры ARM и преобразованных до 16-разрядных кодов, т.е. выполняет альтернативный набор 16-битных команд. Длина команд Thumb составляет половину длины стандартных 32-разрядных команд, что позволяет существенно сократить необходимые объёмы памяти программ (порядка 30 %), а также использовать более дешёвую 16-разрядную память. При выполнении эти команды дешифруются процессором в эквивалентные операции ARM, выполняемые за то же количество тактов. Более короткие коды операций в целом дают большую плотность кода, хотя некоторые операции требуют дополнительных команд. В ситуациях, когда порт памяти или ширина шины ограничены 16 битами, более короткие коды операций режима Thumb становятся гораздо производительнее по сравнению с обычным 32-битным ARM-кодом, так как меньший программный код придется загружать в процессор при ограниченной пропускной способности памяти.

Thumb-2 (являющийся смесью ARM и Thumb) — технология, стартовавшая с ARM1156 core, анонсированного в 2003 году. Он расширяет ограниченный 16-битный набор команд Thumb дополнительными 32-битными командами, чтобы задать набору команд дополнительную ширину. Цель Thumb-2 — достичь плотности кода, как у Thumb, и производительности, как у набора команд ARM на 32 битах. Можно сказать, что в ARMv7 эта цель была достигнута. Thumb-2 расширяет как команды ARM, так и команды Thumb ещё большим количеством команд. Язык «Unified Assembly Language» (UAL) поддерживает создание команд, как для ARM, так и для Thumb из одного и того же исходного кода. Версии Thumb на ARMv7 выглядят, как код ARM. Все кристаллы ARMv7 поддерживают набор команд Thumb-2, а некоторые кристаллы, вроде Cortex-m3, поддерживают только Thumb-2. Остальные кристаллы Cortex и ARM11 поддерживают наборы команд как Thumb-2, так и ARM.

Архитектура ARM имеет много версий, на сегодняшний день (2017) последняя это ARMv8-A семейства Cortex-A50, кстати весной 2017 года компания ARM представила два процессорных ядра Cortex-A75 и Cortex-A55. Мы с Вами не рассматриваем разработки сторонними компаниями, владеющими архитектурной лицензией от ARM, которая разрешала реализацию запатентованных инструкций. Мы с Вами познакомимся с архитектурой ARMv7E-M на ядре Cortex-M4, работая с микроконтроллером STM32F303VCT6 на отладочной плате STM32F3 Discovery. Выше я писал, о переходе на arm ради производительности и функциональности, но также мы расширим немного кругозор, изучим новую технологию и научимся ее интегрировать в проекты, совмещая с другими технологиями. В следующей записи познакомимся с  микроконтроллером STM32F303VCT6, рассмотрим его архитектуру, и научимся с ним работать. На этом сегодня и остановимся. Всем пока.

Просмотрено 2989 раз.

Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 14. Использование DMA

Что такое DMA и зачем это нужно

DMA (Direct Memory Access) — технология прямого доступа к памяти. Эта технология позволяет быстро и без использования центрального процессора пересылать данные из одной области памяти в другую. При этом для такой пересылки вместо ЦП используется свой специальный контроллер, который называется контроллером DMA.

Контроллер DMA работает независимо от ЦП и параллельно с ним. Таким образом использование DMA позволяет экономить ресурсы ЦП, который во время операций пересылки данных с помощью DMA может заниматься какими-то другими полезными делами.

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

Возможности и работа DMA в stm32

В микроконтроллеры stm32 может быть встроено до 2-х контроллеров DMA — DMA1 и DMA2. Они имеют следующие особенности:

  • 12 независимо конфигурируемых каналов: 7 для DMA1 и 5 для DMA2
  • Возможность использования в качестве источника или приёмника данных Flash, SRAM и периферийных модулей, подключенных к шинам APB1, APB2 и AHB
  • Аппаратный запрос от каждого периферийного модуля подключен к одному из 12 каналов
  • Возможность генерации программного запроса по каждому каналу
  • Приоритеты между запросами от разных каналов одного контроллера DMA настраиваются программно и могут иметь 4 уровня: very high, high, medium, low. В случае, если для двух каналов установлен одинаковый приоритет, более приоритетным считается канал с меньшим номером
  • Независимая установка размера порции данных для источника и приёмника (байт, 16-битное полуслово или 32-битное слово)
  • Поддержка кольцевого буфера (когда данные пишутся в буфер по кругу)
  • Возможности передачи данных из памяти в память, из памяти в периферию, из периферии в память или из периферии в периферию
  • 3 флага событий (Half Transfer, Transfer Complete и Transfer Error) логически объединённых в один запрос прерывания для каждого канала
  • Программируемое количество передаваемых данных (количество порций) — до 65535 (то есть если данные передавать 32-битными словами, то максимум можно передать 65535*4 = 262140 байт, — почти 256 кбайт)

Карта запросов модуля DMA1:

Карта запросов модуля DMA2:

Как вообще работает DMA? Всё происходит следующим образом:

  • В периферийном модуле происходит событие, по которому через определённый для этого периферийного модуля канал генерируется запрос к DMA (генерация запроса к DMA должна быть разрешена в настройках самого периферийного модуля)
  • Контроллер DMA обрабатывает пришедший запрос в соответствии с настройками и установленным приоритетом канала, через который пришёл запрос
  • Как только контроллер DMA получает доступ к периферии (выполняет передачу одной единицы информации) — он посылает сгенерировавшему запрос периферийному модулю сигнал подтверждения
  • При получении сигнала подтверждения периферийный модуль снимает свой запрос
  • Как только периферийный модуль снимает свой запрос — DMA контроллер отменяет сигнал подтверждения
  • Если есть ещё запросы от периферии — начинает обрабатываться следующий запрос (опять же в соответствии с установленным приоритетом)

Сама передача данных состоит из трех шагов:

  • Загрузка данных из регистра периферии или из памяти по адресу, записанному во внутреннем регистре текущего адреса источника (этот регистр программно недоступен). Начальный адрес, используемый для первой передачи, прописывается в регистр DMA_CPARx или в регистр DMA_CMARx (в зависимости от направления передачи)
  • Сохранение загруженных данных в регистре периферии или в памяти по адресу, указанному во внутреннем регистре текущего адреса приёмника (этот регистр программно недоступен). Начальный адрес, используемый для первой передачи, прописывается в регистр DMA_CPARx или в регистр DMA_CMARx (в зависимости от направления передачи)
  • уменьшение значения регистра-счётчика DMA_CNDTRx, который содержит количество оставшихся транзакций

В зависимости от настроек, после каждой транзакции модуль DMA может автоматически инкрементировать адреса источника и/или приёмника. Эта возможность настраивается для источника и приёмника независимо друг от друга установкой/сбросом битов PINC и MINC в регистре DMA_CCRx. Причём, в зависимости от установленных для источника и приёмника размеров порции данных адрес автоматически инкрементируется на 1, 2 или 4.

Если канал сконфигурированв нормальном режиме, то после обнуления счётчика транзакций новые запросы к DMA обслуживаться не будут. Чтобы включить обслуживание новых запросов — нужно сначала программно взвести счётчик (записать в регистр DMA_CNDTRx новое значение). Сделать это можно только предварительно выключив соответствующий канал DMA (при выключении канала его настройки не сбрасываются).

В кольцевом режиме (circular mode) значение счётчика автоматически устанавливается к начальному значению после выполнения последней запланированной транзакции (то есть после достижения нуля). Одновременно с этим адреса внутренних регистров текущих адресов сбрасываются к начальным адресам, прописанным в регистрах DMA_CPARx, DMA_CMARx. Кольцевой режим можно включить/выключить установкой/сбросом бита CIRC регистра DMA_CCRx.

Режим пересылки данных из памяти в память выбирается установкой бита MEM2MEM в регистре DMA_CCRx. В этом режиме контроллер DMA начинает выполнять передачу данных сразу после включения канала установкой бита EN регистра DMA_CCRx, то есть не дожидаясь внешнего аппаратного запроса. Не знаю зачем этому режиму дали такое название, я бы лучше назвал его режимом без внешнего триггера, поскольку фактически в этом режиме вы можете как и раньше пересылать данные не только из памяти в память, но и из памяти в регистры периферии, и из регистров периферии в память, и из регистров в регистры, просто теперь каждая транзакция запускается не по событию от периферии, а автоматически, пока не обнулится счётчик (или вообще бесконечно, если для канала выбран кольцевой режим).

Регистры

DMA_ISR — регистр статуса прерываний. Биты этого регистра содержат флаги событий для каждого канала. Они доступны только для чтения, а сбрасываются записью 1 в соответствующий бит регистра DMA_IFCR.

  • GIFx: глобальный флаг прерывания для канала x (x=1..7). Устанавливается в 1 аппаратно в случае возникновения одного из прерываний TE, HT или TC. Сбрасывается программно, записью единицы в соответствующий бит регистра DMA_IFCR.
  • TCIFx: флаг окончания передачи. Устанавливается в 1 аппаратно после обнуления счётчика передаваемых данных. Сбрасывается программно, записью единицы в соответствующий бит регистра DMA_IFCR.
  • HTIFx: флаг окончания передачи половины данных. Устанавливается в 1 аппаратно после отправки половины запланированных данных (когда счётчик уменьшается наполовину). Сбрасывается программно, записью единицы в соответствующий бит регистра DMA_IFCR.
  • TEIFx: флаг ошибки передачи. Устанавливается в 1 аппаратно при возникновении ошибок передачи (при попытках работы с физически нереализованными или зарезервированными адресами памяти). Сбрасывается программно, записью единицы в соответствующий бит регистра DMA_IFCR.

DMA_IFCR — регистр сброса флагов статуса прерываний. Установка битов этого регистра приводит к сбросу флагов прерываний в регистре DMA_ISR. Биты регистра DMA_IFCR доступны только для записи.

  • CGIFx: установка этого бита в 1 приводит к сбросу флагов GIFx, TCIFx, HTIFx и TEIFx (x=1..7 — номер канала) в регистре DMA_ISR
  • CTCIFx: установка этого бита в 1 приводит к сбросу флага TCIFx (x=1..7 — номер канала) в регистре DMA_ISR
  • CHTIFx: установка этого бита в 1 приводит к сбросу флага HTIFx (x=1..7 — номер канала) в регистре DMA_ISR
  • CTEIFx: установка этого бита в 1 приводит к сбросу флага TEIFx (x=1..7 — номер канала) в регистре DMA_ISR.

DMA_CCRx — регистры настройки каналов (x=1..7 — номер канала).

  • EN: включение/выключение канала
  • TCIE: разрешение(1)/запрет(0) прерывания по событию TC (переданы все данные, счётчик обнулился)
  • HTIE: разрешение(1)/запрет(0) прерывания по событию HT (передана половина данных, счётчик уменьшился наполовину)
  • TEIE: разрешение прерывания по событию TE (ошибка передачи)
  • DIR: направление передачи данных. 0 — читать из периферии (и писать в память), 1 — читать из памяти (и писать в периферию)
  • CIRC: включение/выключение циклического режима передачи (1 — circular mode, 0 — normal mode)
  • PINC: включает(1)/выключает(0) инкрементирование адреса периферии после каждой транзакции
  • MINC: включает(1)/выключает(0) инкрементирование адреса памяти после каждой транзакции
  • PSIZE[1:0]: определение размера единицы данных для периферии. Может принимать следующие значения:
    • 00: 8 бит
    • 01: 16 бит
    • 10: 32 бита
    • 11: зарезервировано
  • MSIZE[1:0]: определение размера единицы данных для памяти. Может принимать следующие значения:
    • 00: 8 бит
    • 01: 16 бит
    • 10: 32 бита
    • 11: зарезервировано
  • PL[1:0]: определение уровня приоритета канала. Может принимать следующие значения:
    • 00: Low (низкий)
    • 01: Medium (средний)
    • 10: High (высокий)
    • 11: Very high (очень высокий)
  • MEM2MEM: включает(1)/выключает(0) режим передачи из памяти в память

DMA_CNDTRx — регистры-счётчики (x=1..7 — номер канала). В младшие 16 бит этих регистров прописывается количество данных для передачи (то есть сколько транзакций нужно выполнить с соответствующим каналом). Каждый из этих регистров обладает следующими особенностями:

  • Значение в регистр можно прописать только когда соответствующий канал выключен
  • После включения канала регистр становится недоступен для записи
  • Значение в регистре автоматически декрементируется после каждой транзакции
  • После того, как значение регистра станет равным нулю — новые запросы к DMA от соответствующего канала перестают обслуживаться
  • Если для соответствующего канала установлен циклический режим передачи, то после обнуления регистра в него автоматически загружается начальное значение

DMA_CPARx — регистры адреса (x=1..7 — номер канала). Здесь содержатся начальные адреса регистров периферии в которую или из которой нужно передавать данные по запросу от соответствующего канала. Доступ автоматически выравнивается на границу полуслова или слова, в зависимости от установленного для периферии размера порции данных (достигается игнорированием одного или двух младших бит регистра адреса). Регистры не могут быть перезаписаны пока соответствующий канал включен.

DMA_CMARx — регистры адреса (x=1..7 — номер канала). Здесь содержатся начальные адреса областей памяти в которую или из которой нужно передавать данные по запросу от соответствующего канала. Доступ автоматически выравнивается на границу полуслова или слова, в зависимости от установленного для памяти размера порции данных (достигается игнорированием одного или двух младших бит регистра адреса). Регистры не могут быть перезаписаны пока соответствующий канал включен.

Для модуля DMA2 существуют точно такие же регистры, только x в них может принимать значения 1..5, а не 1..7 (поскольку в DMA2, в отличии от DMA1, всего 5 каналов, а не 7).

Техника программирования DMA

Работать с DMA достаточно просто. Всё, что от Вас требуется — это настроить соответствующий канал и далее только обрабатывать события (которых как мы помним для канала всего 3) или прерывания от них, а также, возможно, взводить счётчик передаваемых данных.

Как обрабатывать события и прерывания — решать только Вам, а вот порядок настройки канала приведён ниже:

  1. Установить в регистре DMA_CPARx (x — номер канала) начальный адрес регистра периферии в которую/из которой будут передаваться данные
  2. Установить в регистре DMA_CMARx (x — номер канала) начальный адрес области памяти в которую/из которой будут передаваться данные
  3. Прописать в регистре DMA_CRDTRx (x — номер канала) количество передаваемых данных (количество транзакций)
  4. Установить в регистре DMA_CCRx (x — номер канала) приоритет настраиваемого канала (биты PL[0:1]), направление передачи данных, режим (circular/normal), отметить нужно или не нужно инкрементировать адреса периферии и памяти после каждой транзакции, установить размеры порций данных для периферии и для памяти, а также настроить прерывания
  5. Включить канал, установив в 1 бит EN регситра DMA_CCRx (x — номер канала)
  6. Ну и конечно нужно не забыть разрешить слать запросы к DMA в настройках самого периферийного модуля.

В библиотеке StdPeriph настройку канала можно выполнить одной функцией — DMA_Init, для включения/выключения используется функция DMA_Cmd.

Примеры работы с DMA приводить не буду, их можно посмотреть в примерах работы с другими модулями (например, в примерах работы с UART или ADC), так что на этом всё.

  1. Часть 1. Установка MDK, создание проекта, основы Keil uVision
  2. Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32
  3. Часть 3. Карта памяти контроллеров STM32, методы работы с памятью
  4. Часть 4. Регистры, старт и режимы работы контроллеров STM32
  5. Часть 5. Как залить прошивку в контроллер
  6. Часть 6. Настройка системы тактирования
  7. Часть 7. Работа с портами ввода-вывода
  8. Часть 8. Процедуры на ассемблере для STM32
  9. Часть 9. Система прерываний
  10. Часть 10. CMSIS, использование стандартных библиотек и функций
  11. Часть 11. Подключение и использование драйверов из пакета StdPeriph
  12. Часть 12. Работа с модулями USART и UART.
  13. Часть 13. Работа с модулями ADC
  14. Часть 14. Использование DMA
  15. Часть 15. Таймеры. Глава 1 — Введение. Простейшие таймеры
  16. Часть 15. Таймеры. Глава 2 — Таймеры общего назначения TIM9 — TIM14
  17. Часть 15. Таймеры. Глава 3 — Таймеры общего назначения TIM2 — TIM5
  18. Часть 15. Таймеры. Глава 4 — Продвинутые таймеры TIM1, TIM8
  19. Часть 16. Создание устройства USB HID в Keil uVision при помощи библиотечного компонента USB
  20. Приложение 1. Набор инструкций THUMB-2 и особенности их использования
  21. Приложение 2. Таблица векторов прерываний для семейств STM32F101, STM32F102, STM32F103
  22. Приложение 3. Драйвера и функции библиотеки StdPeriph

Основы программирование микроконтроллеров на базе ядра ARM Cortex M

Целевая аудитория: Студенты бакалавриата 2 курса, владеющие языком С и желающие познакомиться с программированием современных микроконтроллеров

Время проведения занятий: Четверг 10:00 -11:30. Начало занятий 01.03.2019

Максимальная численность группы: 12 человек

Преподаватель курса: Ассистент каф. САУ Гречухин Михаил Николаевич

Цель курса: Познакомить студентов с современными микроконтроллерами на базе ядра ARM CORTEX M (М3 и М4), с современными средами и средствами разработки ПО для систем на базе МК, дать базовые знания об архитектуре и структуре микроконтроллерной системы, об основных периферийных устройствах МК.

Описание курса. Курс предназначен для студентов, желающих развить навыки программирования на языке С применительно к микроконтроллерным системам на востребованной элементной базе. В рамках освоения курса студенты познакомятся с архитектурой МК, изучат работу с основными периферийными устройствами, освоят работу с современными IDE для микроконтроллерной разработки. Практикум выполняется на отладочных платах на базе МК STM32F411RE на ядре Cortex M4F с разнообразной периферией: датчики, средства визуализации, двигатели и т. д.

Программа курса

  1. Знакомство с архитектурой МК или что у него под капотом (гарвардская архитектура, организация памяти, конвейеризация вычислений).
  2. Конфигурирование МК с помощью регистров. Практикум по теме: задания на отработку поразрядных операций, манипуляции над отдельными битами целого числа.
  3. Тактирование. Характеристики тактового сигнала. Потенциальное и динамическое управление. Источники тактового сигнала в МК STM32.
  4. Обзор библиотеки CMSIS. Обзор IDE Keil MDK-ARM, создание и настройка проекта. Работа с эмулятором и настройка проекта для отправки на плату.
  5. Система GPIO (General Purpose Input-Output). Режимы работы и настройки. Управление выводом сигналов на отдельные ножки в режиме ввода-вывода общего назначения. Практикум по теме: говорим «Hello, world!» по-микроконтроллеровски – мигание диодом на плате с программной задержкой.
  6. Прерывания. Событийно-управляемый режим работы системы. Приоритеты прерываний, источники прерываний. Практикум по теме: улучшаем мигалку – добавляем реакцию на нажатие кнопки.
  7. Таймеры. Режимы работы таймеров. Регистры настройки таймеров. Прерывания таймеров. Каналы таймеров общего назначения. Практикум по теме: делаем высокоточный таймер для мигалки Общетематический практикум: ARMовый парктроник с индикацией на диодные линейки.
  8. Периферийные интерфейсы МК. Интерфейс I2C и его использование Практикум по теме: получение данных об атмосферном давлении с помощью барометра с интерфейсом I2C
  9. ШИМ и её применение для управления аналоговыми устройствами Практикум по теме: разгон и торможение двигателем без педали газа! Практикум по теме: Плавно меняем яркость диодов.
  10. Проект: торможение гусеничной платформы перед препятствием.

iTAG: инструментарий отладки и тестирования | arm

[Что потребуется]

1. Компьютер Windows PC с портом USB.
2. Кабель miniUSB.
3. Утилита обновления программного обеспечения (DfuSe) от компании STMicroelectronics [2].
4. Утилита программирования iTAG.ZERO от компании iSystem [3].
5. Среда разработки iTAG winIDEA™ IDE от компании iSystem [4].
6. Перемычка 2.54 мм.

Программное обеспечение iTAG.ZERO [3] и iTAG winIDEA™ IDE [4] можно загрузить бесплатно и без регистрации. ПО DfuSe [2] также бесплатно, но для его загрузки требуется регистрация на сайте STMicroelectronics.

[Подготовительные действия]

• Загрузите и установите DfuSe [2], включая драйверы.

• Загрузите ПО iTAG [3], и запишите его копию в папку BIN утилиты DfuSe.

• Загрузите и установите winIDEA [4] (включая драйверы).

• Отключите от компьютера или выключите все другие аппаратные средства iSystem, если таковые имеются.

• Убедитесь, что компьютер, используемый для прошивки iTAG-ZERO, не занят какими-то другими требовательными к ресурсам приложениями.

[Процедура прошивки по шагам]

1. Перед подключением iTAG-ZERO к USB установите перемычку J2.

2. Подключите устройство кабелем miniUSB к компьютеру.

3. Потребуется несколько секунд на обнаружение системой Windows устройства и завершение установки драйвера устройства перепрошивки (DFU Device driver). После завершения установки драйвера устройство DFU должно отображаться в дереве Менеджера Устройств.

4. Снимите перемычку J2.

5. Запустите утилиту iTAG utility в папке DfuSe\BIN, и следуйте инструкциям, которые дает программа перепрошивки.

6. Дождитесь окончания процесса. После завершения перепрошивки firmware должен загореться светодиод.

7. Начнется процедура установки драйвера iTAG. Устройство iTAG должно пройти энумерацию, после чего оно будет видно в дереве Менеджера Устройств.

8. Для закрытия окна утилиты перепрошивки нажмите любую клавишу.

9. Запустите среду разработки winIDEA, откройте любой проект или создайте новый.

10. Выберите в меню Debug -> Run Control -> CPU Reset.

11. Появится окно, приглашающее обновить firmware. Выберите Yes.

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

12. Выберите Yes в окне окончательного подтверждения обновления.

13. Дождитесь завершения процедуры обновления, после чего закройте все окна диалога.

Теперь Вы можете подключить iTAG к целевой отлаживаемой системе и начать отладку. Обратите внимания, что первая инициализация сессии отладки после обновления firmware или после обновления winIDEA будет происходить несколько дольше, чем все последующие инициализации сессии отладки.

Совет: в случае возникновения проблем Вы можете разблокировать устройство приложением DfuSeDemo от компании ST. Оно устанавливается вместе с инсталляцией пакета DfuSe [2]. Запустите это приложение, выполните двойной клик на Option Bytes, и выберите Yes, когда появится запрос на подтверждение снятия защиты (remove protection). Имейте в виду, что это полностью сотрет информацию о лицензировании в устройстве, если таковая имеется. Также имейте в виду, что серийный номер устройства поменяется после повторного программирования.

Краткий учебный курс — Самоучитель — Программирование микроконтроллеров AVR — быстрый старт с нуля

 

— страница  7 —

Всё о прошивке AVR
микроконтроллеров AVR

Чем и как «прошить» МК AVR, ATmega, ATtiny.

Как загрузить программу в микроконтроллер.

Как запрограммировать микроконтроллер AVR.

Я советую прошивать микроконтроллер AVR из удобного интерфейса программирования встроенного в компилятор CVAVR  CodeVisionAVR

Можно через простейший адаптер — буквально «пять проводков» (схема ниже) соединяющих принтерный порт ПК с прошиваемым микроконтроллером AVR.

Но более удобны программаторы подключаемые в USB или COM порты ПК — особенно в USB.

 

Книги по электронике и микроконтроллерам  скачать в библиотеке

Страницы курса :   заглавная    1   2   3   4   5   6   7   8   9

Задачи-упражнения курса по AVR  —   там
 

Скачать весь курс по AVR одним архивом на заглавной странице курса.

Электрический ток. Закон Ома
Последовательное и параллельное соединение проводников
Правила Кирхгофа для разветвленных цепей
Работа и мощность тока
Электронно-дырочный переход. Транзистор

 


ПРОГРАММИРОВАНИЕ  AVR

Результат написания и компиляции программы — файл-прошивку с расширением .hex (и возможно файл  .epp  или  .bin  с содержимым для EEPROM МК) нужно записать («зашить», «загрузить», «прожечь») в МК AVR.

МК AVR можно (пере-) программировать не менее 10000 раз, при чем это можно делать прямо в устройстве в котором они будут работать — такое программирование называют «в системе» — «ин систем программин» или ISP.

Компания ATMEL рекомендует установить на плате устройства специальный разъем для подключения программатора. 

Например 6 штырьков для ISP прошивания AVR

Вид сверху платы на штырьки. 

 


или 10 штырьков  в аналогичном порядке ( NC — значит не подключен )

Все контакты ISP разъема подсоединяются к  ножкам  МК в соответствии с названиями сигналов !  Исключения указаны ниже.


Вывод 2 нужно подключить к » + » питания МК если вы собираетесь использовать программатор питающийся от вашего же устройства — например фирменный ISP AVR либо если вы хотите питать ваше устройство от USB при использовании программатора указанного выше.  Для адаптера «5 проводков» этот вывод не подключается.


Для ISP программирования достаточно 5 контактов. Соответственно и разъем который вы будете использовать может быть любым удобным для размещения на плате и имеющий минимум 5 контактов — например в один ряд.

Я использую и считаю это очень удобным 6 штырьков расположенные в 1 ряд, в том порядке как расположены ножки программирования у ATmega16 ( рисунок есть на страничке 6 ) — при этом разводка линий программирования получается простейшей.  Такой разъем легко применять и для 28 выводных AVR  ATmega8  ATmega48 ATmega88  ATmega168 ATmega328 только сделать отдельный проводник для подключения к контакту RESET.

 

   
 

ВНИМАНИЕ !

1) в ATmega64 и ATmega128  выводы MOSI и MISO не применяют для ISP программирования.  Используются другие выводы МК  !

Внимательно смотрите ДатаШит вашего МК !    
 

в ATmega128 ATmega64  сигналы ISP программатора

MISO подключают к ножке PE1

MOSI подключают к ножке PE0


Для ATmega640 -1280 -1281 -2560 -2561 смотрите в даташит 
Table 163. Pin Mapping Serial Programming.

2) Вывод PEN нужно подключить к питанию VCC резистором 1-10  кОм

3) в ATmega128 и ATmega64 есть FUSE бит совместимости со старым МК ATmega103 и с завода он запрограммирован в «0» на совместимость.
См  Table 117. Extended Fuse Byte. 
При прошивании ATmega128 и ATmega64 вам нужно сделать этот fuse «1» —  «не запрограммирован».    Убрать галочку в CVAVR.
 

Подробней о фьюзах ниже и на стр. 2 курса

 
   

Трудно сразу написать правильно работающую программу, даже после прогона и отладки в софт эмуляторе — симуляторе VMLAB или PROTEUS ваше реальное устройство с реальным AVR может делать не то, что вы от него ожидаете.

Значит в программу нужно будет вносить изменения, перекомпилировать и снова зашивать в МК AVR, и так раз 20-40 и более поэтому разумно использовать отличный программатор AVR в уже имеющемся у вас CVAVR в котором вы правите программу.  


 

В меню CVAVR  «Сеттинс  -> Программер» вам надо выбрать ваш адаптер (подробней про адаптеры ниже!) для программирования.

 

Вариант 1.   Только если вы понимаете что такое фьюзы и знаете как правильно их установить !!!   Вы можете в компиляторе CodeVisionAVR открыть меню «Проджект -> Конфига -> Афта Мэйк»  и отметить чек бокс  «Program the chip». Появится окно программирования-прошивания AVR 

 

В этом окне надо установить параметры программирования — фьюз биты и лок биты — об этом подробней написано ниже. После установки параметров программирования нажмите ОК.

 

Теперь после компиляции программы без ошибок в окне с результатами компиляции вам будет доступна кнопка «Program» — нажмите на нее и, если все подключено правильно, произойдет программирование МК — т.е. файл .hex будет загружен в память программ МК и (если используется в программе) файл EEPROM будет в нее загружен. Затем МК будет «сброшен» (на ножку RESET будет подан лог. 0 а затем опять «1») и AVR начнет выполнять уже новую, только что прошитую (загруженную в него) программу.

Вам даже не нужно будет отсоединять адаптер программирования от вашего устройства  если вы не используете в вашем устройстве последовательный интерфейс SPI. 

… и так до окончательной отладки устройства.

 

Вариант 2.   Если вы не устанавливали чек бокс  «Program the chip» или

Если вы хотите без компиляции прошить с помощью CVAVR готовые файлы прошивки .hex и возможно содержимое EEPROM в микроконтроллер AVR

1) запустите программатор CVAVR кнопочкой «МИКРОСХЕМА» правее «красного  
    жучка» в верхней панели инструментов.  Появится окно программирования AVR

  

2) Откройте меню «File» затем «Load FLASH» — выберете файл прошивки .hex который нужно прошить в AVR (CVAVR поддерживает и другие форматы, а не только .hex) и щелкните «Открыть».  

3) Если у вас есть информация для загрузки в EEPROM AVR то откройте меню «File» затем «Load EEPROM» — выберете файл .epp  (CVAVR поддерживает и другие форматы) и щелкните «Открыть».

Если вы не используете EEPROM или не меняете ее содержимое — поставьте галочку у «Preserve EEPROM» — это ускорит прошивание.

4) Установите параметры программирования — фьюз биты и лок биты.

Лок биты устанавливают уровень защиты вашей программы от чтения из памяти AVR — это актуально для коммерческих изделий. Для защиты прошивки отключите отладочные интерфейсы JTAG или «уан вая» и  установите «Programming and Verification disabled».

 

ГЛАВНОЕ это правильная установка фьюз битов — fuse AVR …

5) Запрограммируйте AVR не кнопкой «Program All», а через меню «Program» —  Стереть, потом FLASH, потом EEPROM и если надо и если вы уверены в их установке то и фьюзы. 

После прошивания, если вы сделали все правильно, AVR начнет выполнять уже новую программу.

 

   
 

В А Ж Н О !  

В диалоге настройки прошивания отключите программирование фьюзов МК  уберите галочку у Program Fuse Bit(s) — если не разобрались четко, что они делают и как правильно их установить ! 

Иначе вы можете отключить режим ISP или внутренний RC-генератор и для следующего программирования вам понадобится ставить кварц с конденсаторами или даже искать:

Параллельный программатор для AVR


Но популярному ATtiny2313 даже параллельный программатор
не всегда поможет !    В Errata на ATtiny2313 было написано:

Parallel Programming does not work
Parallel Programming is not functioning correctly. Because of this, reprogramming
of the device is impossible if one of the following modes are selected:
– In-System Programming disabled (SPIEN unprogrammed)
– Reset Disabled (RSTDISBL programmed)
 

 
   

 

в ATmegaXXX с завода включен внутренний RC генератор
на  частоте 1 МГц  
( уточните это по ДШ  и его возможные частоты )

Если вам нужна другая частота или нужно включить внешний кварцевый или керамический резонатор — вам нужно при программировании МК установить фьюзы (Fuses) по таблицам из ДШ ( Даташит AVR на русском языке ) или по таблице фьюзов на стр. 2 или по таблице установки фьюзов ниже :

ЗАПОМНИТЕ :

НЕ запрограммированный  фьюз        1

ЗАпрограммированный   фьюз             0
 

Пример: Чтобы включить в ATmega16 внешний кварцевый резонатор (говорят просто — «кварц») с частотой от 3 до 8 МГц с конденсаторами ( по схеме рис. 12 ДШ ) найдите в ДШ раздел «System Clock» — «системный тактовый сигнал».

В таблице 2 указаны комбинации фьюзов для разных источников тактового сигнала.
Далее написано что с завода МК поставляется с такой комбинацией фьюзов

CKSEL   0001     SUT  10       CKOPT   1


По таблице 4  находим :   в ATmega16 для кварца с частотой от 3 до 8 МГц  нужны конденсаторы от 12 до 22 пФ и  вот  такая  комбинация  фьюзов :

CKSEL   1111     SUT  11       CKOPT   1

Вот скриншот с такой установкой фьюзов в программаторе компилятора  CVAVR


Сняв галочку Program Fuse Bit(s) вы cможете не менять установку фьюзов при прошивании AVR !

НЕ НАЖИМАЙТЕ кнопку «Program All»  —  она прошивает и фьюзы не смотря на отсутствие галочки.

 

Обязательно !!! Прочитайте текущую комбинацию фьюзов в микроконтроллере — «Read» -> «Fuse bit(s)» и скопируйте ее в окно фьюзов.  теперь при случайном нажатии кнопки «Програм ол» в МК прошъется та же комбинация фьюзов которая есть сейчас.

 


Фьюз биты — фьюзы AVR — у которых нет галочки после прошивки AVR будут
равны «1» — т.е. будут  не запрограммированными.

 

Реклама недорогих радиодеталей почтой:


Для прошивания МК используйте меню  «Program»

Вначале  «Erase chip» — стереть чип.

Затем «FLASH»  — прошить программу в МК

И если надо то  «EEPROM» — прошить в EEPROM.


 

Для использования ATmega16 (и других мег) с внешним кварцевым или керамическим резонатором на частотах выше 8 МГц вам нужно установить фьюзы как в примере выше, но запрограммировать CKOPT  
значит сделать его «0».

Т.е. вам нужна такая комбинация:

CKSEL   1111     SUT  11       CKOPT   0

 

CKOPT   — нужен и тогда когда вы хотите взять с XTAL2 тактовый сигнал для другого
микроконтроллер или тактируемого прибора в вашем устройстве.
 

Фьюзы  SUT   — определяют быстроту запуска генератора тактового сигнала,
более детально это описано в даташите в таблицах до 12.
 


Фьюзы ATtiny2313 описаны в конце следующей страницы курса.

 

 

Интерфейс программирования AVR — Адаптер для соединения МК с ПК при прошивании.

Для соединения компьютера с ISP разъемом устройства на AVR Советую сделать адаптер от STK200  — это «правильные 5 проводков» с микросхемой буфером снижающим вероятность случайного повреждения порта ПК.

В установках компилятора CodeVisionAVR интерфейс «5-проводков» называется  «Канда системз STK200+/300».  Меню «сеттингс» — «программер». В этом же диалоге можно понизить частоту с которой программатор будет обмениваться с прошиваемым МК увеличивая множитель задержки.

Частоту тактирования сигнала SCK программатором при прошивании можно установить в диалоге программирования в CVAVR. 



Снижение частоты на SCK повышает помехоустойчивость при прошивке.

Программа узнаёт адаптер STK200 по перемычкам на разъеме параллельного порта к которому он подключается — должны быть соединены двумя перемычками пары выводы: 2 и 12,  3  и 11. 

   
 

Внимание!  

Для программирования к МК должно быть подключено питание. Например +4…+5.5 вольт ко всем выводам МК в названии которых есть VCC , а  0 вольт ко всем выводам GND (это «общий» провод).    

Обязательно поставьте подтягивающий резистор 10 кОм от ножки RESET AVR на питание VCC и конденсатор 0.01-0.15 мкФ (в апноутах AVR040 и AVR042 рекомендуют 0.01 мкФ) от RESET на GND .

Пример схемы там

 
   

 
Если в МК нет внутреннего генератора тактового сигнала (например старые AVR серии AT90sXXXX или мега побывавшая в чьих то шаловливых руках изменивших фьюзы до того как попасть к вам) то нужно подключить кварц
на 1 — 8 МГц и два конденсатора от 15 до 33 пФ. 

Либо подать тактовый сигнал 0.8-1.5 МГц от внешнего источника —
например генератора на микросхеме 74hc14 (аналог 1553ТЛ2) или на таймере LM555.

Вот как сделать простой генератор тактовой частоты :

 


Программатор  AVReAl  может программировать МК без кварца и без конденсаторов ! Он выводит тактовый сигнал на выв. 5 LPT его нужно подать на ножку XTAL1 МК и добавить в командной строке AVReAL специальный ключ  «-o0».  Программатор  AVReAl  позволяет назначать какие ножки LPT порта использовать — это будет полезно когда часть ножек LPT вы уже спалите  
  🙂

 

Если вы считаете эту информацию полезной, пожалуйста, помогите информировать в интернете о курсе — просто щелкните по банеру. Большое спасибо !
Electronic Banner Exchange (ElBE)


Тактовый сигнал генерирует и самодельный программатор AVR
для  USB — смотрите ниже на этой странице.

 

   
 

Я использую самый простой вариант адаптера
STK200 — «для самых ленивых»   

Пять поводков соединяющих линии параллельного (LPT) порта ПК и AVR так же как на схеме STK200 выше, но без микросхемы буфера. 

Лучше все же токоограничительные резисторы от 150 до 270 ом впаять Береженого бог бережет !
 

Проводки не более 15 см длиной !

 
   

 

 

Адаптер «5-проводков» прекрасно работает с компилятором CVAVR  CodeVisionAVR.

Я проверял «проводки» при питании МК ATmega64L от 3,0 до 5,3 вольт, а так же с ATmega16, ATmega48, ATtiny26, ATtiny261, ATtiny13, ATtiny2313 — программирует всегда без сбоев!  

Всё о прошивке AVR Прошивка AVR PIC прошивки Программирование PIC и AVR

   
 

Советую для изготовления адаптера взять » принтерный» шнур — он длинный и экранированный, а не экранированные проводки не стоит делать более 10-15 см.

 
   

 


Питать устройство при программировании можно :

— сетевым адаптеры от бытовых устройств понизив напряжение до 5 вольт. 

— батарейками ! Достаточно три батарейки по 1,5 вольт последовательно. 

+5 вольт можно взять с вывода 1 гейм порта компьютера или из провода включенного в гнездо USB.

Желательно питать устройство от ПК!  В этом случае «земля» вашего устройства будет соединена с корпусом ПК и можно будет безопасно подключать и отключать разъем программирующего адаптера.

 

 
   
 

ВНИМАНИЕ ! 

Вначале старайтесь соединять «земли» (металлические корпуса, «общие» провода) устройств — для уравнивания их потенциалов ! 

Удобно подпаять к проводнику GND устройства проводок с «крокодильчиком» который прицепите к металлу ПК у LPT или COM портов перед подключением разъемов или сигнальных линий, проводов.

Теперь БЕЗОПАСНО соединять разъемы
и затем подавать питание на устройство.

 
   

 

 


Не поленитесь:  спаяйте адаптер STK200 на микросхеме буфере по рисункам внизу страницы  — так как LPT порт компьютера более нежен чем COM — соответственно его спалить проще…     Спалите LPT и будете меня ругать! 

А  я  предупреждал !

 

 

Поставщики AVR говорят что ATTiny2313 поступают с завода с настройкой внутреннего RC-генератора на 4МГц (в даташите указано 8 МГц) с делителем частоты на 8  — т.е. частота тактирования всего 500 КГц. Значит частота на линии SCK, формируемая программатором, не должна быть выше 120..125кГц. 
 


Программатор встроенный в CodeVisionAVR позволяет настроить эту частоту правильно. Выше было написано как.
 

AVReal  тоже.  


 

   
 

Если вы хотите использовать ножки МК SCK, MOSI, MISO в вашем устройстве то подключайте другие компоненты к ним через резисторы 4.7 КОм — чтобы не мешать программированию.

Так рекомендовано в апноуте AVR042

Для Мега64, -128 вместо MOSI и MISO используются другие ножки для ISP программирования !

 
   

 

 

Если у вас нет LPT порта сделайте
Аналог  «5 проводков» для COM-порта.

 


Или соберите простой, дешевый и хороший
USB программатор для AVR

Прошитый микроконтроллер для сборки USB программатора AVR вы можете заказать по почте.

 

   
 


Существуют специальные программы «бутлодеры» (bootloader — начальный загрузчик) 
которые записываются в микроконтроллер способами перечисленными выше и после этого микроконтроллер может сам, при включении, закачивать в себя программу (например из ПК через адаптер USB-UART rs232 COM port — схема в задаче 4 курса) и запускать ее выполнение.

Есть много бесплатных загрузчиков

Вот Bootloader AVR_Arduino.

Вот хороший:   Bootloader AVR.

Вот еще:    MegaLoad Bootloader

STC создал загрузчик bootloader размером 256 байт с поддержкой быстрого страничного режима записи.


Прошитые загрузчиком bootloader микроконтроллеры AVR PIC вы можете заказать по почте.

 
   

 

 

 Дальше — стр. 8 курса.

 

 

Назад на стр. /06.htm — задачи управжнения по AVR

 

 

ниже  

Cписок Апноутов для AVR примеры применения микроконтроллеров.

 

И много полезной информации !
 

Ассемблер для микроконтроллера с нуля. Часть 1. Начало пути


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

Не смотря на то, что знаком с МК я уже достаточно давно, знания мои в этой области далеки не то чтобы от совершенства, но даже от полноты. Это явилось причиной серьёзных сомнений: браться ли за столь обширную тему? В конце концов верх взяла мысль о том, что для кого-то эта информация (пусть и не полная) окажется важной и полезной.

Содержание / Contents

Изначально, записывая «шпаргалки» для детей, я определил пару условий в изложении, чтобы оно, с одной стороны, не отпугнуло читающего в самом начале пути, а с другой — дало бы общее понимание работы микроконтроллеров и снизило барьеры при переходе от одного типа МК к другому:
• Рассматривать несколько МК разных архитектур и, желательно, разных производителей. При этом, давать такое объяснение принципа работы, которое подходило для всех рассматриваемых МК, но не было совсем уж популистским.
• При разборе практических примеров, обойтись без использования специализированной среды программирования (IDE). Тема МК сама по себе не самая примитивная, а необходимость вникать параллельно в работу нескольких IDE для разных МК оптимизма начинающему никак не прибавляет.
Эти же принципы, несколько расширив их, я решил перенести на статью. Объектами изучения нам послужат микроконтроллеры:

ATTINY85-20PU DIP8


ATMEGA8A-PU


Макетная плата STM32F401


Ebyte SoC nRF52832 тестовая плата
Если точно такой платы не найдёте, можно купить модуль nRF52832 и распаять отладочную плату.

nRF52832
Минимум пинов, которые необходимо вывести:
• GND,
• VCC,
• SWDIO и SWDCLK для программирования и отладки,
• Reset,
• несколько GPIO.
В файловый архив выложен мануал этого модуля.


USBasp

st-link v2

USB-UART адаптер Ch440
Макетная плата

Соединительные провода разного типа

Потенциометры

Светодиоды В качестве среды программирования мы будем использовать обычный блокнот Notepad++, компилировать написанную программу посредством компилятора GCC от GNU. С отладкой кода нам помогут программы Tetminal и PuTTY, а с его загрузкой в МК — avrdude и openocd.1. Скачать и установить Notepad++.
2. При необходимости выбрать русский язык в Settings/Preferences/General/Localization.
3. В Плагины/Управление плагинами, во вкладке Доступные выставить галочки напротив Explorer и NppExec и нажать кнопку Установить.
4. Выставить галочки напротив Плагины/Explorer/Explorer, Плагины/NppExec/Show Console и Follow $(CURRENT_DIRECTORY). Слева и снизу от окна редактора появятся окна проводника и консоли, соответственно.
5. В Опции/Определение стилей выбрать подходящий стиль и для языков С, Makefile и Assembler настроить подходящие цвета и размеры шрифтов.
6. Чтобы настройки стиля вступили в силу в Синтаксисы выбрать A/Assembly, C/C или M/Makefile при работе с соответствующим файлом.
1. Создать на удобном для вас диске папки:
• GNU,
• GNU/AVR,
• GNU/AVR/avrdude,
• GNU/ARM,
• GNU/MinGW.
2. Скачать и распаковать в папку GNU/ARM файлы Arm GNU Toolchain 6.3.1 — Windows и openocd-20200701.7z.
Переименовать распакованные папки в armGnuToolchain и OpenOCD.
3. Скачать и распаковать в папку GNU/AVR файл AVR 8-bit Toolchain v3.62 — Windows.
Переименовать распакованную папку в avrGnuToolchain.
4. Скачать и распаковать в папку GNU/AVR/avrdude файл avrdude-6.1-mingw32.zip.
5. Скачать файл mingw-get-setup и запустить его, указав GNU/MinGW как папку для установки. В ходе установки будет запущен MinGW Installation Manager, в котором достаточно выбрать базовый пакет (Basic Setup) и нажать Installation/Apply Changes.

Если с установкой возникли проблемы, можно скачать готовый вариант папки MinGW из архива.
6. В Панель управления\Система\Дополнительные параметры системы\Переменные среды\Переменные среды для пользователя\Path\ добавить пути к папкам:
• GNU\ARM\armGnuToolchain\bin
• GNU\ARM\OpenOCD\bin
• GNU\AVR\avrGnuToolchain\bin
• GNU\AVR\avrdude
• GNU\MinGW\msys\1.0\bin

7. Перезагрузить компьютер.

Скачать и распаковать на удобном для вас диске программы Terminal 1.9b и PuTTY
В архив выложены rar-файлы всех упомянутых выше программ.Драйвер USBasp также выложен в архив, а ST-link v2 устанавливается автоматически при первом подключении к компьютеру. Оба программатора после установки должны отобразиться в «Диспетчере устройств» Windows.Как бы мне ни хотелось сразу перейти к практике, придётся сделать отступление в теорию. Попытаюсь ограничиться её минимумом, который облегчит понимание практического материала в последующем. Более того, уже в этой главе мы начнём знакомиться с некоторыми реальными командами МК AVR и ARM. Добавлю, что местами буду приводить англоязычный вариант терминов и аббревиатур: все-же чтения даташитов и мануалов вам не избежать, а их издатели упрямо не желают переходить на великий и могучий.В моём восприятии, как программиста, микроконтроллер — две большие кучи регистров. В первую кучу (память программ) мы загружаем программу в виде последовательностей нулей и единиц. При этом, значительная доля содержания программы сводится к своевременной записи правильного набора нулей и единиц в нужный регистр второй кучи (памяти данных), либо чтению из него этих наборов. В случае языка ассемблер мы имеем дело, по большей части, именно с регистрами памяти данных, поэтому выясним для начала, что они из себя представляют.
Уверен, вам известен такой элемент, как D-триггер (далее — триггер) и его основные свойства:
1. Выход триггера T может находиться только в одном из двух логических состояний — 1 (на выходе — напряжение питания) или 0 (на выходе — земля).
2. Значение (0 или 1) со входа D переносится (записывается) на выход T триггера по фронту синхронизирующего (тактового) сигнала С и сохраняется до следующей записи либо отключения питания.

Если взглянуть на триггер в плоскости информации, можно сказать, что он хранит 1 бит данных со значением 0 или 1.
Соединив параллельно несколько триггеров, мы и получим регистр, разрядность или битность которого определяется количеством составляющих его триггеров. Совокупность линий данных триггеров регистра принято называть шиной данных. Тактовый сигнал для всех триггеров регистра — единый, т. е. перенос значений с линий шины данных на выходы (запись в регистр) происходит одновременно для всех триггеров. Нумерация битов регистра ведётся справа-налево, начиная с нулевого. Обычно, битность регистров МК кратна восьми (8, 16, 32).


Пример 8-битного регистра приведён на Рисунке 5.

Если необходимо увеличить объём хранимой информации, регистры объединяют в массивы. В этом случае, чтобы обеспечить запись в определённый регистр массива (или чтения из него), требуются линии выбора, которые все вместе именуются шиной адреса. Номера или адреса регистров массива также начинаются с нулевого значения. Пример массива из 4 регистров, в котором с целью экономии входы и выходы триггеров сведены в одну двунаправленную шину, представлен на Рисунке 6.


Чтобы не загромождать рисунок, впредь будем изображать регистр без линий шин данных/адреса и тактирования, обозначая его как rn (где, n — адрес регистра), а хранимые в нём данные — помещать внутрь квадратов, символизирующих триггеры.
Не берусь утверждать, что регистры МК организованы на базе именно D-триггеров. Более того, физическая суть записи в регистры памяти программ (flash-память) — совершенно иная. Тем не менее, принципы хранения и движения оперативной информации в микроконтроллерах я постарался передать верно.В завершение — о единицах измерения хранимой в регистрах информации и некоторых общепринятых терминах.

Восемь бит информации составляют 1 байт. Биты и байты с самым маленьким номером в заданном диапазоне часто называют младшими, а с самым большим номером — старшими. То же самое, кстати, относится и к адресам. Для обозначения многобайтных данных иногда применяют термин «слово» («word»).

В случае, когда речь идёт о тысячах байт, может возникнуть лёгкая путаница. Дело в том, что исторически использовалась единица 1 килобайт, равная 1024 байт.
Думаю, поборники «чистоты во всём», возмущённые тем, что «кило» — 1024, а не 1000, добились, в конце концов, принятия двух единиц измерения:
1 килобайт (KB) — 1000 байт
1 кибибайт (KiB) — 1024 байт.
Не уверен, что жизнь программистов после этого стала стремительно улучшаться, и поэтому не стал бы тратить ваше время на подобную информацию, однако с таким многообразием единиц измерения согласились, кажется, не все.
При прочтении даташитов, вы убедитесь, что производители МК по-прежнему используют приставку K, подразумевая 1024 байт. Кроме того, в следующих главах нам предстоит делать расчёт адресов регистров, исходя из их общего количества, поэтому давайте договоримся: в рамках данной статьи 1K байт — это 1024 байт.

Поскольку регистры ничего, кроме 0 и 1, содержать не могут, можно сказать, что микроконтроллер оперирует в поле двоичной системы счисления.
На Рисунке 7 нули и единицы, записанные в регистр, образуют 8-битное двоичное число 10101010. В программировании двоичное число предваряют символами 0b: 0b10101010.

На первых порах представление числа в двоичном формате при написании программы может показаться наиболее естественным и понятным. Но, попробуйте набрать в текстовом редакторе несколько раз одну и ту же комбинацию из 32 нулей и единиц, не вызвав при этом ряби в глазах и сомнений, что в том или ином разряде не перепутаны 0 и 1, и вы поймёте, что с этим надо что-то делать. Поэтому, обычно применяют привычное десятичное или шестнадцатеричное представление числа.

Обычно, десятичные числа используют в программе, когда речь идёт о численном выражении какой-либо величины (например, 5 секунд или 12 тонн).

В случае шестнадцатеричной системы счисления перед числом прописываются символы 0x. Одно из бесспорных преимуществ шестнадцатеричного представления заключается в том, что каждые два разряда числа, начиная с младшего, составляют 1 байт. К примеру, байты числа 0×12A57F — 0×12, 0хA5 и 0×7F. О пользе этого свойства вы узнаете в главе, посвящённой практике. Добавлю, что эта система, помимо программы, широко используется в документации МК: адреса регистров в даташитах и мануалах представлены в шестнадцатеричной форме.

Для уверенности в том, что набранное вами десятичное или шестнадцатеричное число отражает требуемую комбинацию 0 и 1 в двоичном представлении, надо бы знать, как переводится число из одной системы счисления в другую. Однако, не буду забивать вам головы информацией о методах такого перевода: полагаю, что для начала вполне достаточно использовать калькулятор Windows.


Как видите, число, записанное в регистр на Рисунке 7 — 170 в десятичной и 0xAA в шестнадцатеричной системах счисления.По ходу программы с числами, записанными в регистры, производятся два основных типа операций — математические и логические (их ещё называют битовыми). Если с глубокой математикой вы вряд ли столкнётесь на начальном этапе обучения, то логические операции придётся использовать уже при первых шагах, в связи с чем рассмотрим их подробнее.
В Таблице 1 приведены названия, символы и формы записи основных логических операций.
Логические операции применимы к числам любой длины, поэтому для обсуждения результатов их работы остановимся на 8-битных числах.Запись операции читается как «сдвинуть число m влево n раз». На Рисунке 9 приведён пример 2-кратного сдвига влево числа m = 3 (0b00000011), записанного в регистр r0.
Обратите внимание, что биты, освобождающиеся справа от числа при сдвиге его влево, заполняются нулями.Запись операции читается как «сдвинуть число m вправо n раз», а сама операция работает так же, как и предыдущая, но в обратном направлении.
Если на Рисунке 9 поменять местами верхний и нижний регистры, получится иллюстрация двукратного сдвига вправо числа 12 (0b00001100). С применением этой операции значение каждого бита числа меняется на противоположное, т.е инвертируется, поэтому её часто называют инверсией. На рисунке 10 результат инверсии числа A = 15 (0b00001111) из регистра r0 записан в r1 как число С = 240 (0b11110000).
Перед тем, как перейти к оставшимся трём операциям из Таблицы 1, на всякий случай уточню, что проведение логической операции между двумя числами означает попарное её применение к битам этих чисел с одинаковым порядковым номером. Результат равен 1 только если оба бита пары равны 1.
Результат равен 1 если хотя бы один из двух бит пары равен 1.
Результат равен 1 только, если один из двух бит пары равен 1, а другой — 0.

Отмечу, что форма записи логической операций в Таблице 1 и соответствующая ассемблерная команда (инструкция) МК — не одно и то же. Кроме того, на иллюстрациях операций между двумя регистрами (И, ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ) результат, для наглядности, записывается в третий регистр, в реальности же он, обычно, сохраняется в первом из двух, участвующих в операции регистров.
В Таблице 2 приведены некоторые инструкции логических операций МК AVR и ARM с кратким описанием их работы.

Чтобы вам было легче понять, а мне — объяснить суть вопроса, представим 8-битный регистр (Data Register, DR), входящий в состав микроконтроллера и ответственный за связь последнего с внешним миром. Подключим к выводам DR лампочки и договоримся о двух вещах:

1. Мы не можем делать с DR ничего, кроме записи/чтения числа в/из него, да и то не напрямую, а только через вспомогательный регистр r0. К чему такие сложности, вы поймёте из следующего раздела главы.

2. Логика нашего устройства — прямая т. е. число 1 в n-м бите DR включает соответствующую лампу, а 0 — выключает.

Включим жёлтую лампу на выводе 7, записав через r0 в регистр DR число 0b10000000 (128 в десятичной системе счисления), и пусть себе горит. Поскольку речь пойдёт о логике, забудем на время об электрической грамотности и изобразим наше устройство следующим образом:

Как включить красную лампу, подключённую к выводу 4, а затем выключить её, не меняя состояние включённой ранее жёлтой лампы или, если обобщить, как изменить состояние одного или нескольких битов регистра DR, не меняя состояния остальных? Легко сообразить, что для включения красной лампы надо добавить 1 в четвёртый бит и полученное число 0b10010000 (144) записать в DR.

Чтобы выключить красную лампу, не меняя состояния жёлтой, необходимо вернуть в DR число 128. Казалось бы, всё просто и можно вполне обойтись без логических операций. Но, обратим внимание на следующую не очевидную деталь: формируя числа для включения/выключения лампы, мы не должны забывать, что в седьмом бите в обоих случаях должна быть единица. Запомнить номер одного бита — 7 — не сложно так же, как и его состояние, тем более, что оно неизменно. К тому же, регистр у нас — всего один, да и картинка перед глазами облегчает дело.

В реальности картинок, как вы понимаете, нет, а регистров может быть сотни, к тому же 32-битных. Более того, по ходу программы их значение может меняться не один раз. Выходит, программист, чтобы поменять состояние одного бита, должен помнить текущее состояние оставшихся 31 битов для формирования правильного числа. И так — для сотен регистров. И это ещё не самое худшее. Не редко бывает так, что состояние одного или нескольких битов регистра определяется внешними устройствами (кнопками, сенсорами и т. д.) и тогда мы можем даже не знать, каково их текущее состояние.

Короче говоря, нужен механизм, пригодный для чисел любой длины и позволяющий нам менять состояние заданного бита, не затрагивая остальные, т. е. не утруждая себя знанием их текущего состояния. Такой механизм реализуется с помощью логических операций при условии наличия ещё одного вспомогательного регистра — r1.

Операция ИЛИ позволяет записать 1 в любой бит числа, не меняя состояния остальных битов, для чего потребуется:
1. Считать текущее значение DR в r0.
2. Записать в r1 число, в котором значение требуемого бита равно 1, а остальных — 0. В случае с красной лампой это — 4-й бит, а число — 0b00010000.
3. Применить операцию ИЛИ посредством инструкции OR r0, r1 (или ORR r0, r1 — для ARM), результат работы которой, как видно из Таблицы 2, запишется в r0.
4. Скопировать полученное число из r0 в DR.


Очевидно, операция дополнительно к жёлтой не включит ни одной лампы, кроме красной. Более того, если бы мы вдруг забыли, что красная лампа уже включена (1 в четвёртом бите DR до операции) и, тем не менее, провели операцию, это было бы лишь повторное включение и без того включенной лампы, что — не смертельно.
Если включить воображение, можно сказать, что в ходе операции число в r1 накладывается, подобно маске, на число в r0 для получения требуемого результата, поэтому далее будем использовать этот термин.

Операция ИСКЛЮЧАЮЩЕЕ ИЛИ меняет значение требуемого бита на противоположное, не затрагивая остальные биты, если:
1. Считать текущее значение DR в r0.
2. Записать в r1 такую же, как и в предыдущем случае, маску — 0b00010000.
3. Применить операцию ИСКЛЮЧАЮЩЕЕ ИЛИ посредством инструкции EOR r0, r1.
4. Скопировать полученное число из r0 в DR.
На Рисунке 17 приведён пример включения и последующего выключения красной лампы без изменения состояния жёлтой посредством двойного применения инструкции EOR r0, r1.


С помощью операции И можно обнулить любой бит числа, не меняя состояния остальных, для чего нужно:
1. Считать текущее значение DR в r0.
2. Записать в r1 маску, в которой значение требуемого бита равно 0, а остальных — 1, т. е. 0b11101111 в нашем случае.
3. Применить операцию И посредством инструкции AND r0, r1.
4. Скопировать полученное число из r0 в DR.
Как легко убедиться, будь любая другая лампа, помимо жёлтой, включена до операции, её состояние не изменилось бы и после. Опять же, если красная лампа будет изначально выключена (0 в четвёртом бите DR до операции), мы, применив по забывчивости операцию И, всего лишь получим попытку её повторного выключения.

Всё, изложенное выше, работает, при внесении соответствующего изменения в маску, и в случае, когда речь идёт об одновременном изменении состояния нескольких битов. Например, если параллельно с красной, требуется включать/выключать лампу на нулевом выводе DR вид маски будет следующим:

• 0b00010001 — для операций ИЛИ/ИСКЛЮЧАЮЩЕЕ ИЛИ,
• 0b11101110 для операции И.

Есть ещё одна польза от применения логической операции И — возможность проверить текущее состояние любого бита регистра. Предположим, что включение/выключение красной лампы обусловлено положением внешнего переключателя, подключённого ко 2-му выводу DR. Тогда, следует периодически:
1. Считывать текущее значение DR в r0.
2. Записывать в регистр r1 маску, в которой 2-й бит равен 1, а остальные — 0, т. е. 0b00000100.
3. Применять операцию И посредством инструкции AND r0, r1.


Вы можете, меняя на Рисунке 19 содержимое r0 до операции, убедиться, что после операции в него всегда будет возвращаться число 0 (0b00000000), кроме единственного варианта — когда состояние 2-го бита DR, а значит и r0, до операции, равно 1. В этом случае в r0 после операции запишется число 0b00000100, что и будет сигналом для включения красной лампы. Во всех остальных случаях её следует выключать.
Приведённый пример проверки состояния справедлив и для комбинации битов. То есть, если бы включение красной лампы определяла комбинация из единиц в 0-м и 5-м битах регистра DR, то маской и числом в r0 после операции, обуславливающим включение красной лампы, будет 0b00100001. Приведу самый простой пример их использования. Если записать в регистр r0 число 1 (0b00000001), а затем последовательно выполнять 7 инструкций сдвига влево (LSL r0) и 7 вправо (LSR r0), получится эффект «бегущего огня».

Ещё об одном распространённом варианте применения операции сдвига. Вы наверняка заметили из Рисунка 9, что единичный сдвиг влево равноценен умножению на 2, а вправо — делению на 2. Учитывая, что сдвиг исполняется МК быстрее, чем умножение/деление, программисты зачастую используют первую операцию взамен второй, когда скорость работы программы критична.
Операция сдвига влево, наряду с операцией НЕ, используется, помимо прочего, для формирования битовых масок, о чём — ниже.

Если в вопросе безопасного изменения состояния требуемого бита мы избавились от головных болей, то формирование самой битовой маски всё ещё остаётся хлопотным делом, особенно в случае с ARM, когда нужно без ошибок набрать число из 32 нулей и единиц. Однако, есть приёмы, позволяющие свести процесс формирования двоичного числа любой длины к комфортному минимуму, чем и займёмся.

Раз уж мы стали использовать инструкции МК, познакомимся ещё с одной — записи числа в регистр. На Рисунке 20 приведён пример инструкции записи в регистр r1 маски включения красной лампы для обоих ядер МК.


Мнемоники (LDI и LDR) инструкции схожи, поскольку в их основе лежит одно и то же слово «load». Поэтому впредь наряду с «запись в регистр» будем использовать выражение «загрузка в регистр».
Глядя на число в правой части Рисунка 20. попытайтесь оценить, сколько непередаваемых эмоций может принести вам работа в лоб с 32-битными масками. Вообще то, общепринятые правила позволяют не отражать незначащие разряды, т. е. число 16 можно записать в обоих случаях как 0b10000, а компилятор сам дополнит недостающие слева нули в соответствии с разрядностью МК.

Ну, а если, всё же, все разряды значащие? Тогда никуда не денешься: придётся набирать этих 8- или 32-главых монстров в тексте программы или на калькуляторе, чтобы получить их десятичный (шестнадцатеричный) аналог. В любом случае риск поставить не туда 0 или 1 остаётся.

Попробуем обойтись малой кровью.
Начать следует с того, что компилятор переводит в двоичное представление не только десятичные и шестнадцатеричные числа, попадающиеся на его пути, но и числа, выраженные в форме записи логических операций. Если хотите понять, что это значит на нормальном человеческом языке, вернёмся к Таблице 1 и вспомним, что 4-кратный сдвиг влево числа 1 выражается формой и даёт результат, представленные на Рисунке 21.

Приглядевшись повнимательнее к Рисунку 21, вы заметите две вещи:
1. В результате операции получилось число 16 (0b00010000), т. е. маска для включения красной лампы.
2. Число n в форме записи (т.е. — 4) фактически указывает на номер бита, в котором должен оказаться после операции младший бит сдвигаемого числа (в нашем случае — единица). В этом контексте можно сказать, что результатом операции n-кратного сдвига влево числа 1 всегда будет число, в котором n-й бит равен единице, а остальные — нулю. Имейте в виду, что все эти фокусы не проходят со сдвигом вправо.

Так вот, мы можем в инструкциях МК из Рисунка 20 вместо двоичного представления числа 16 записать форму 4-кратного сдвига влево числа 1:

,
а компилятор, встретив такую конструкцию, заменит её на число, в котором 4-й бит равен единице, а остальные — нулю, т. е. приведёт всё к виду на Рисунке 20.

Как быть с маской для погашения красной лампы — числом 0b11101111? Вы, скорее всего, уже поняли, что оно — инверсия предыдущей маски 0b00010000. Это позволяет использовать конструкцию


при компиляции, которой, с учётом скобок, определяющих последовательность действий, произойдёт следующее:
1. Формирование числа 0b00010000.
2. Инверсия числа из п. 1 в искомую маску 0b11101111.

В случае, если необходимо менять состояние одновременно несколько битов, не затрагивая остальные, соответствующие числа для маски выражается так:


Принимая во внимание скобки, компилятор в первом случае:
1. Сформирует число, в котором k-й бит равен 1, а остальные — 0.
2. Сформирует число, в котором m-й бит равен 1, а остальные — 0.
3. Сформирует число, в котором n-й бит равен 1, а остальные — 0.
4. Применит операцию ИЛИ между числами из п. п.1 и 2., в результате чего получится новое число с единицами в битах k и m и нулями — в остальных.
5. Применит операцию ИЛИ между числами из п. 3 и 4. с получение окончательного числа с единицами в битах k, m и n и нулями — в остальных.

Во втором случае шестым пунктом добавится инверсия числа из п. 5.

Остался один не обязательный, но очень полезный штрих.
Само по себе число в строке кода не несёт полезной информации, если только оно не количественное выражение чего-либо (2 слонёнка, 5 мартышек и т. п.). Увидев в чужой программе конструкцию подобную той, что на Рисунке 22, вы сможете догадаться лишь, что автор собирается что-то делать с 4-м битом. Замена формы логической операции на число 16 только прибавит загадочности. Наверное, потому и называют такие числа магическими, что выяснить их назначение можно только с помощью магии. Даже собственный код недельной давности, утыканный магическими числами, может ввести вас в ступор, а если вы рискнёте передать его в таком виде коллеге по цеху или заказчику, будьте готовы узнать о себе много нового и интересного.

Ситуацию можно улучшить, добавив к строке комментарий, что, мол, готовится включение красной лампы. Но, комментарий в каждой строке — перебор в другую сторону. Поэтому в случае на Рисунке 22. предпочтительнее использовать условное название или макроопределение для числа 4.
Все используемые в тексте программы макроопределения прописываются до их применения и в ассемблере от GCC имеют следующий общий вид:

НАЗВАНИЕ = значение

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


Для нас такая запись, согласитесь, более информативна, чем предыдущая, а компилятор все встреченные в коде макроопределения RED_LAMP заменит числом 4.

Есть ещё одна веская причина, оправдывающая применение макроопределений. Представьте, что вы практически закончили программу, в десятках разных мест которой включаете/выключаете красную лампу без использования макроопределения. И тут заказчик сообщает, что по соображениям топологии платы красную лампу решено подключить к выводу 6, а вам надо всего лишь внести крохотные, по его мнению, изменения в коде. Не факт, что вы найдёте все четвёрки, подлежащие замене на 6, а это чревато странностями в работе всего устройства. При использовании же макроопределения замену придётся делать лишь раз — в самом макроопределении.

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

• зелёный светодиод — к 0-му,
• синий светодиод — к 17-му,
• мотор — к 31-му.

Инструкции чтения из DR в r0 и обратного копирования мною сознательно опущены, поскольку потребовалось бы объяснение особенностей их применения, что не имеет отношения к теме этого раздела. Поговорим об этом в следующей, практической, части статьи.

На Рисунке 27 приведена блок-схема модели микроконтроллера.
Несмотря на то, что это — всего лишь модель, к тому же очень упрощённая, постараюсь на её примере дать функциональную картину МК, в объёме, достаточном для первоначального этапа, и в общих чертах справедливую как для AVR, так и для ARM. Случаи же, когда детали устройства и работы реального микроконтроллера и модели принципиально не совпадают, будут освещены по ходу текущей главы, либо — в практической части статьи.

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

Через этот блок МК общается с внешними устройствами. В контексте этого общения задача программиста заключается в том, чтобы в заданное время на определённом выводе МК:
• обеспечить наличие логических 1 или 0 (напряжения питания или 0В, соответственно),
• считать текущее состояние — логические 1 или 0.
• считать значение аналогового сигнала. Как правило, выводы МК для реализации этой функции жёстко определены. В нашей модели такой вывод — с порядковым номером 0.Назначение этого блока заключается в непосредственном исполнении задачи, определённой выше:
• Порт ввода/вывода (ПВВ, GPIO) обеспечивает запись на выводы МК, либо считывание с них цифрового сигнала — логических 1 или 0,
АЦП (ADC) измеряет уровень аналогового напряжения на выводе 0 МК.
Таймер считает поступающие на него тактовые импульсы. Зная период такта, мы можем вычислить общую продолжительность счёта, что даёт возможность с точность до одного тактового периода задавать время чтения информации с выводов МК, либо записи на них.

Обратиться к элементам блока периферии (настроить их или записать/считать данные) мы можем только через соответствующие регистры, расположенные в памяти данных ядра.
В реальных МК модулей периферии значительно больше, а их функциональные возможности — шире. Более того, они могут дублироваться (3 порта, 2 таймера, 5 АЦП и т. д.), но всё это не меняет сути дела.

В нашей модели в состав ядра входят:
• Центральный процессор (ЦПУ). Именно для него мы пишем программу. В моменты, когда требуется произвести арифметическую или логическую операцию, ЦПУ привлекает арифметико-логическое устройство (АЛУ).
• Память программ. Сюда загружается написанная нами программа. В нашем случае память состоит из двадцати двух 16-битных регистров с адресами от 0 до 21. Программа это — набор инструкций, понятных ЦПУ. Длина инструкции нашего МК составляет 16 бит, поэтому в каждый регистр может быть записана лишь одна.
Содержимое памяти программ сохраняется даже, если питание МК отключено.
• Память данных. Как следует из названия, здесь хранятся данные. О том, какие именно — чуть позже. Организована память данных в виде 22 регистров, длиной 8 бит каждый.
Информация в памяти данных сохраняется только, если МК запитан, иначе все её регистры обнуляются. В реальном МК при сбросе/отключении питания отдельные регистры памяти данных могут принимать ненулевое значение, определённое производителем.
• Программный счётчик (ПС, PC) содержит адрес инструкции, которую ЦПУ должен исполнить следующей.Помимо упомянутых блоков на схеме присутствуют:
• Генератор тактовых импульсов (ГТИ). Этот узел запускает работу МК и задаёт её скорость. Единственное, что действительно следует знать о ГТИ реальных МК на начальном этапе, так это — возможность выбора элемента, определяющего его частоту — внутренняя RC-цепочка или внешний кварцевый резонатор. О том, как осуществить этот выбор, мы поговорим в одной из последующих глав.
• 8-битная шина данных, через которую блоки МК обмениваются информацией. Ширина шины данных определяет разрядность МК.
• 16-битная шина команд, по которой ЦПУ считывает инструкции из памяти программ.Выясним, как устроены, функционируют и взаимодействуют между собой блоки и отдельные элементы МК. Кроме того, постараемся понять общую структуру и алгоритм работы программы, создаваемой нами.Как вы видите, первыми в этой памяти расположены два регистра общего назначения (РОН, GPR), знакомые вам r0 и r1. В реальных МК регистров общего назначения — более десяти. Я не случайно выделил эти регистры, ЦПУ и АЛУ одним синим цветом. Дело в том, что ни ЦПУ, ни АЛУ не имеют прямого доступа ко всем остальным, кроме РОН, регистрам памяти данных. Не существует команды для ЦПУ «записать число 5 в регистр данных ПВВ с адресом 3». Для реализации этой операции потребуется минимум две инструкции:
1. Загрузить число 5 в r0.
2. Скопировать число из r0 в регистр с адресом 3.

Точно также АЛУ не может сложить прямо числа, которые записаны, к примеру, в регистрах с адресами 10 и 11 или применить к ним логическую операцию. Для этого необходимо считать числа из указанных регистров в r0 и r1 и уже между ними проводить требуемую операцию.

Следом за РОН идут регистры периферии. В рассматриваемой модели их — по два на каждый модуль (регистр настройки и данных).

Назначение регистров данных следующее:
По сути это — регистр DR из предыдущего раздела главы. Когда мы выводим данные вовне, значение (1 или 0) в n-ном бите регистра данных обуславливает логическое состояние (1 или 0, соответственно) на выводе МК с таким же номером. В случае же чтения данных извне ситуация обратная: логические 1 или 0 на n-ном выводе МК отражаются как 1 или 0 в бите регистра данных c порядковым номером n.По мере счёта значение регистра данных таймера увеличивается от нуля до 0b11111111 (255), а затем опять сбрасывается в 0. И так — до тех пор, пока тактирование таймера не будет отключено.Сюда АЦП записывает двоичное представление измеренного на выводе 0 МК значения аналогового напряжения.Теперь — о регистрах настроек. Биты этих регистров отвечают за следующее:
Если значение n-го бита — 1, вывод МК с таким же номером работает как выход, 0 — как вход.
• 0-й бит. Если значение бита — 1, тактирование таймера включено, 0 — выключено.
• 1-й и 2-й биты. Если комбинация их значений — 00, то частота тактирования таймера равна частоте ГТИ, 01 — частота ГТИ/2, 10 — частота ГТИ/64, 11 — частота ГТИ/128.
• 3-й бит. Если значение бита — 1, разрешено прерывание таймера — сигнала о том, что он досчитал до своего максимума и сбросился в ноль, 0 — прерывание запрещено.
• 4-й — 7-й биты не используются, т. е. зарезервированы.
• 0-й бит. Если значение бита — 1, тактирование АЦП включено, 0 — выключено.
• 1-й и 2-й биты. Этими битами также, как и у таймера, регулируется частота тактирования АЦП.
• 3-й бит. 1 — разрешен сигнал (прерывание) АЦП о том, что измерение завершено и результат преобразования сохранён в регистре данных АЦП. 0 — прерывание запрещено.
• 4-й бит. С записью 1 в этот бит стартует измерение. Значение бита автоматически сбрасывается в 0 по завершению измерения.
• 5-й — 7-й биты зарезервированы.

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

Предположим, что мы решили собрать устройство на базе нашего МК, которое каждые 255 секунд с максимальной скоростью измеряет аналоговый сигнал от фоторезистора, подключённого к выводу 0, и, в зависимости от уровня освещённости, включает/выключает лампу на выводе 4.

Примем частоту ГТИ за 128Гц. Тогда в регистры настроек периферии нужно записать через РОН следующие числа:
ПВВ
0-й вывод МК должен работать как вход (значение соответствующего бита регистра настроек — 0), а 4-й — как выход (значение бита — 1). Поскольку направление работы остальных выводов нам не важно, настроим их как входы. Получаем число 0b00010000.

Таймер
• 0-й бит. Разрешаем тактирование — 1.
• 1-й и 2-й биты. Делим частоту ГТИ на 128, т. е. частота тактирования таймера будет 1Гц. Тогда, чтобы переполниться (досчитать до 255) и выдать прерывание ему понадобится как раз 255 секунд. Комбинация значений битов — 11.
• 3-й бит. Разрешаем прерывание таймера — 1.
Искомое число — 0b00001111.

АЦП
• 0-й бит. Разрешаем тактирование — 1.
• 1-й и 2-й бит. Нам нужна максимальная скорость измерения, т. е. частота тактирования АЦП. Отказываемся от деления частоты ГТИ. Комбинация — 00.
• 3-й бит. Разрешаем прерывание АЦП — 1.
В итоге — число 0b00001001.

Алгоритм программы будет выглядеть так:
1. Настраиваем периферию.
2. В цикле, при каждом прерывании от таймера записываем 1 в 4-й бит регистра настроек АЦП, запуская тем самым измерение освещённости. Чтобы не затереть при этом уже записанное в этот регистр число 0b00001001, применяем логическую операцию ИЛИ и маску 0b000010000.
3. По прерыванию от АЦП считываем значение из регистра данных АЦП. Если оно меньше порогового (которое, например, равно 40), включаем лампу, записав 1 в 4-й бит регистра данных ПВВ, в противном случае — гасим.

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

Бит I. Чуть выше мы говорили о битах в регистрах настройки периферии, разрешавших прерывания таймера и АЦП. Эти биты называют битами локального разрешения прерывания. Бит I — в принципе разрешает использовать механизм прерываний, т. е. это — бит глобального разрешения прерываний, без установки программистом в 1 которого локальные разрешения прерываний силу иметь не будут.
Следует отметить, что бит I — особенность МК AVR. В ARM для глобального контроля за прерываниями выделен целый модуль, называемый Nested Vectored Interrupt Controller (NVIC).

Биты Z и N также доступны программисту как для чтения, так и для записи. Однако, для нас, в первую очередь, интересно их свойство автоматически устанавливаться в 1 в определённых случаях:

Бит Z устанавливается в 1 автоматически, если в результате какой-либо операции АЛУ образуется ноль. К примеру, нам нужно узнать, равно ли значение регистра данных таймера 48. Для этого:
1. Считываем значение регистра данных таймера в r0.
2. Загружаем в r1 число 48.
3. Вычитаем значение одного РОН из другого.
4. Если в результате вычитания Z примет значение 1, числа равны.

К автоматической записи в бит N единицы приводит образование отрицательного числа после какой-либо операции АЛУ, что даёт возможность использовать его для проверки условий «больше-меньше». Если в результате вычитания значений двух РОН бит N устанавливается в 1, вычитаемое больше уменьшаемого, и наоборот. Именно этот бит помог бы нам сравнить текущий уровень освещённости с пороговым в вышеприведённом примере.

Второй специальный регистр в памяти данных — указатель стека SP (Stack Pointer). Функция этого регистра настолько сильно взаимосвязана с работой программы, что будет правильнее, если я расскажу вам о нём ниже, при обсуждении памяти программ. Скажу лишь, что сразу после сброса/подачи питания в SP должен быть записан адрес старшего регистра памяти данных (в нашей модели это — 21), поэтому оба регистра окрашены в единый серый цвет.Осталось выяснить, для чего служит область памяти SRAM.
Представьте, что в рассмотренном выше примере устройство должно реагировать не на мгновенное значение освещённости, а на среднее от результатов 5 измерений. Куда размещать массив данных до их усреднения?
Для этого и пригодится сектор SRAM, названный кучей (heap). В общем случае данные размещаются по направлению от младшего адреса (10) кучи к старшему (19).

Функция сектора стек (stack) опять же тесно связана с работой программы и о ней — ниже.

Включите всё ваше воображение и представьте, что я, будучи заместителем директора по кадрам, написал и согласовал с руководством круг обязанностей для специалиста вновь открываемого управления. Название должности, кстати, звучит как «Центральная персона управления» (сокращённо — «ЦПУ»).

Согласно документа, названного для солидности «Основная функция (main)», ЦПУ, придя утром на работу должен включить и настроить печатающую машинку, стукнув по ней три раза, а затем в цикле набирать букву «А» или «Б», в зависимости от того, включена сигнальная лампа на стене или отключена. После набора каждой буквы необходимо совершить два прихлопа и три притопа.
Природа одарила меня ленью и, чтобы не повторять два раза инструкции о притопах и прихлопах, я вынес их в отдельный список под названием «Подпрограмма» и в итоге получил следующее:

«Основная функция (main
1. Включить печатающую машинку.
2. Стукнуть по машинке 3 раза.
3. Если сигнальная лампа включена, набрать букву «А». Иначе — перейти к строке 6.
4. Выполнить подпрограмму.
5. Перейти к строке 3
6. Набрать букву «Б».
7. Выполнить подпрограмму.
8. Перейти к строке 3.

«Подпрограмма»
1. Сделать два прихлопа.
2. Сделать три притопа.
3. Вернуться к основной функции и продолжить её.

Во время исполнения инструкций любого из списков могут произойти следующие события (назовём их «прерываниями»):
1. Звон колокола. При этом автоматически настройки печатающей машинки сбрасываются, а сама она — отключается.
2. Лай собаки.
3. Звонок в дверь.
4. Стук в окно.

ЦПУ, при наступлении любого из указанных событий, должен завершить исполняемую инструкцию, затем всё бросить и отреагировать на каждое событие соответствующим образом. Тут я решил несколько усложнить задачу и сделать реакцию на прерывания двухступенчатой, приложив к каждой ступени отдельный список. Первый список — «Вектор прерывания» — состоит всего лишь из одной инструкции, предписывающей перейти ко второму списку, называемому «Обработчик прерывания», причём для удара колокола обработчиком прерывания служит основная функция. Выглядеть всё это будет так:

«Вектор удара колокола»
1. Перейти к началу основной функции.

«Вектор лая собаки»
1. Перейти к обработчику лая собаки.
«Обработчик лая собаки»
1. Мяукнуть.
2. Вернуться к брошенному делу и продолжить его.

«Вектор звонка в дверь»
1. Перейти к обработчику звонка в дверь.
«Обработчик звонка в дверь»
1. Подпрыгнуть.
2. Вернуться к брошенному делу и продолжить его.

«Вектор стука в окно»
1. Перейти к обработчику стука в окно.
«Обработчик стука в окно»
1. Сделать 5 приседаний.
2. Вернуться к брошенному делу и продолжить его.

Функции по меньшей мере странные, нудные и однообразные, а мне ещё надо срочно подобрать под это дело исполнителя. Естественно, выпускники Гарварда, Кембриджа и прочих оксфордов дружно отказываются выполнять работу, которая может бросить тень на их репутацию и дипломы.

В конце концов находится согласный на всё тип, которого в своё время исключили за неуспеваемость из школы, из-за чего он еле-еле читает и пишет, но считать так и не научился. Понимает и исполняет этот работник только самые простые указания. Помимо всего этого, вследствие продолжительного употребления всяких напитков, память у него отшибло настолько, что инструкции типа «Вернуться туда-то и продолжить то-то» ввергают его в прострацию, поскольку он никак не может запомнить, какую работу только что бросил, а тем более, с какого места её продолжать.

Опасаясь, что с такими способностями и памятью он рано или поздно натворит бед (перепутает списки, вернётся не к тому делу или просто заснёт на рабочем месте), я принимаю превентивные меры:
1. В помощь ЦПУ придаю бухгалтера-АЛУ для ведения счётных операций.
2. Говорю своему охраннику с тёмным прошлым и кличкой «ГТИ», чтобы он задавал исполнителю и бухгалтеру ритм работы, пиная их со строгой периодичностью.
3. Объединяю все списки в один большой («Программа»), в котором:
• присваиваю блокам названия прежних списков,
• применяю сквозную нумерацию строк (впредь, вместо термина «номер строки» будем употреблять «адрес» или «адрес инструкции»).
• меняю все инструкции перехода на однообразное «Перейти к адресу n».

Критический взгляд на Программу, даёт понимание того, что всё ещё осталась пара моментов, которые могут сбить с толку ЦПУ:
• Инструкция «Выполнить подпрограмму» не указывает, где последняя находится.
• Инструкция «Вернуться» стала короче, чем «Вернуться к брошенному делу и продолжить его», но от этого не стала менее загадочной.

Поэтому, исполнителю передаётся маленький прибор («Программный счётчик» или «ПС»), на дисплее которого отображается:
• на инструкции «Перейти к адресу n» — адрес перехода,
• на инструкции «Выполнить подпрограмму» — адрес первой инструкции подпрограммы (13),
• на инструкции «Вернуться» — адрес возврата,

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

Памятуя, что писать и читать вновь нанятый работник всё же умеет, я вручаю ему пару листков:
• Первый листок (пусть он называется «SRAM») разлинован на 12 строк с номерами или адресами от 10 по 21. При необходимости, ЦПУ может записывать данные (количество сделанных приседаний или промежуточные результаты расчётов бухгалтера, к примеру) по адресам 10-19 («куча»). Но, ему под страхом смерти запрещено использовать две последние строки, окрашенные в серый цвет («стек»).

• Во второй листок («Указатель стека» или «SP») исполнитель должен всего лишь один раз, перед включением печатной машинки, записать старший адрес SRAM (т.е. — 21), о чём в программу добавлена соответствующая инструкция (по адресу 4). Кстати, такая запись называется указанием на вершину стека.

Работа ПС, SP и SRAM определённым образом взаимосвязана:
• При каждом ударе колокола все они обнуляются, вместе с отключением печатной машинки.

• При наступлении каждого из трёх оставшихся прерываний автоматически:
а) адрес следующей после исполняемой в данный момент инструкции записывается в SRAM по адресу, указанному в SP,
б) значение SP уменьшается на единицу.
в) адрес вектора прерывания записывается в ПС

• Каждый раз, когда в программе встречается инструкция «Выполнить подпрограмму», автоматически:
а) адрес следующей инструкции записывается в SRAM по адресу, указанному в SP,
б) значение SP уменьшается на единицу.
в) стартовый адрес подпрограммы (13) записывается в ПС.

• Каждый раз, когда в программе встречается инструкция «Вернуться», автоматически:
а) значение SP увеличивается на единицу.
б) значение в SRAM по адресу, указанному в SP, записывается в ПС.

Чтобы быть спокойным, я решаю промоделировать ту или иную рабочую ситуацию: сажаю ЦПУ, АЛУ и ГТИ в одну комнату, включаю сигнальную лампу и бью в колокол. Как вы помните, ПС, SP и SRAM при этом обнуляются, а печатающая машинка отключается со сбросом настроек.

Итак,
1. ЦПУ видит в ПС число 0 и переходит на этот адрес программы.
2. По адресу 0 — переход на адрес 4. ЦПУ убеждается, что в ПС указан тот же адрес и переходит.
3. Осуществляется запись в SP последнего адреса SRAM (21). ПС при этом увеличивается на 1 — до 5.
4. ЦПУ включает печатающую машинку и настраивает её (инструкции по адресам 5,6).
5. Поскольку сигнальная лампа включена, набирается буква «А».
6. На инструкции по адресу 8 («Выполнить подпрограмму»):
• Адрес следующей инструкции (9) записывается в SRAM адресу 21, поскольку именно это число записал ЦПУ в SP чуть ранее.
• Значение SP уменьшается (декрементируется) на 1, т. е. вершина стека теперь — 20.
• В ПС записывается стартовый адрес подпрограммы (13), куда и отправляется ЦПУ.

7. Сделав в требуемых количествах прихлопы и притопы (не забывайте, что ПС на этих инструкциях просто инкрементируется), ЦПУ подходит к адресу 15 (инструкция «Вернуться») и здесь:
• значение SP увеличивается на единицу — до 21.
• Значение из SRAM по адресу 21 (а там у нас — 9) записывается в ПС.
• ЦПУ выполняет инструкцию по указанному в ПС адресу 9, т. е. переходит к адресу 7. В этот момент я выключаю сигнальную лампу.

8. Поскольку лампа выключена, ЦПУ переходит по адресу 10.
9. Во время набора буквы «Б» раздаётся стук в окно. При этом:
• Адрес следующей инструкции (11) записывается в SRAM по адресу 21 (именно до этого значения увеличился SP в п.7).
• Значение SP декрементируется до 20.
• Адрес вектора стука в окно (3) записывается в ПС.
• ЦПУ завершает печатать букву «Б» и переходит по адресу в ПС — 3.

10. Перейдя по адресу 20 (об этом было указано в инструкции по адресу 3), ЦПУ прилежно приседает, а затем осуществляется возврат к адресу 11 в порядке, описанном п. 7.

Вдумчивый читатель может заинтересоваться, почему ЦПУ запрещено делать записи в строке 20 SRAM, если она в приведённых выше десяти пунктах ни разу не использовалась? Да и без указателя стека можно вполне обойтись: при инструкции «Выполнить подпрограмму» и прерываниях просто записать адрес инструкции, следующей за текущей, в 21-ю строку SRAM, а потом благополучно вернуть в ПС.
Давайте примем такой вариант и представим следующее.
1. ЦПУ набрал букву «А» и перешёл к подпрограмме. Адрес следующей инструкции (9) записывается в SRAM по адресу 21.
2. Во время второго прихлопа (адрес — 13) звонят в дверь и:
• При наличии стека и указателя на него адрес следующей инструкции (14) был бы записан в SRAM по адресу 20. Но, мы от них отказались, поэтому число 14 записывается по адресу 21 затирая предыдущую запись (9).
• Адрес вектора звонка в дверь (2) записывается в ПС.
3. ЦПУ переходит к адресу 2, оттуда — к адресу 18, подпрыгивает и возвращается к адресу, записанному в 21-й строке SRAM, т. е. 14.
4. В это время к шефу компании прибывает иностранная делегация и он решает похвастать перед ними тем, как замечательно работает новое управление.
5. Шумной толпой они вваливаются в комнату и видят, что бухгалтер и охранник, разинув рты, уставились на ЦПУ, который безостановочно притоптывает потому, что после каждых трёх притопов вновь возвращается к адресу 14, а адрес 9, куда он должен был в конце концов вернуться, затёрт.

Этим примером я лишь напомнил вам, что прерывание может произойти в любое время: как при исполнении основной функции, так и подпрограммы. Более того, в реальных программах часто используются несколько подпрограмм, вложенных друг в друга. И это ещё не всё. В системах посложнее прерываниям назначаются приоритеты и прерывание с более высоким приоритетом могут происходить во время исполнения обработчика прерывания с приоритетом ниже. Во всех этих случаях не обойтись без участия стека и указателя на него.

1. Все мы имели дело с детской пирамидкой и помним, что кольцо, надетое последним, снимается первым. Стек, как вы наверняка заметили, работает по тому же методу LIFO (Last In First Out): значение, записанное последним, считывается первым.

2. В нашей модели, с целью упростить объяснение и облегчить его восприятие, размеры стека и кучи чётко определены, а ЦПУ в приказном порядке запрещены записи в стек. В реальных микроконтроллерах нет инструментов (специальной инструкции или аппаратного механизма) для разграничения стека и кучи. Кроме того, запись в стек возможна не только автоматически (при переходах в подпрограмму или обработчик прерывания): и в AVR, и в ARM имеется инструкция PUSH rn, которая сохраняет текущее значение n-го РОН в вершину стека. Таким образом, с ростом объёма сохраняемой информации куча и стек движутся навстречу друг другу и может, в конце концов, произойти их наложение: либо стек «продавит» кучу, либо куча «сорвёт» вершину стека.

Оба случая — из разряда самых коварных и неприятных ошибок программиста. Мало того, что компилятор не распознаёт их как ошибку, так они ещё и «блуждающие», т. е. могут проявляться лишь изредка, нанося при это разрушительный урон.

Избежать их позволят несколько простых правил:
• старайтесь не увлекаться вложенными подпрограммами,
• в программах на ассемблере контролируйте использование инструкций PUSH и парной ей POP.
• в программах на С/С++ не злоупотребляйте глобальными переменными.
• при необходимости сохранения в куче постоянного потока данных применяйте циклический буфер.

Ну что же, вроде как всё работает. Я, как напоминание о моих трудах, вешаю на стену увеличенные копии схемы программы, SP и SRAM, рассаживаю троицу по рабочим местам и делаю фотографию для истории.

В своё время, все мои попытки объяснить новичку (к тому же — ребёнку) работу микроконтроллера с использованием полной его функциональной схемы и реальных инструкций ЦПУ особого успеха не принесли. Очень надеюсь, что вариант объяснения, использованный мною выше, будет несколько проще и понятнее, а производители МК простят меня за столь вольные и не всегда справедливые образы.

Перед тем, как закончить с теорией, приведу некоторую информацию по реальным МК, рассматриваемых в данной работе.
Прежде всего — о документации, знакомиться с которой, рано или поздно, вам придётся в любом случае.
В случае с ATtiny85 и ATmega8 вполне достаточно внимательного изучения даташитов.
Для МК на базе ARM информация по ядру и периферии разнесена:
1. STM32F401 Datasheet.
2. STM32F401 Reference Manual.
3. STM32 Cortex-M4 Programming Manual.
1. nRF52832 Product Specification.
1. Cortex-M4 Generic User Guide.
2. Cortex-M4 Technical Reference Manual.
3. ARMv7-M Architecture Reference Manual
Указанные выше документы выложены в архив, и все последующие ссылки будут делаться именно на них.
На рисунке 31. представлены карты памяти ATtiny85 и ATmega8.

Как видите, всё — очень близко к модели из Рисунка 27, за исключением количества регистров.

Память программ
Для обоих МК объём этой памяти составляет 8К или 8 * 1024 = 8192 байт. Организована она в виде массива из 16-битных или 2-байтных регистров в количестве 8192 / 2 = 4096 штук с адресами от 0 (0×0000) по 4095 (0×0FFF). Длина инструкций ATtiny85 и ATmega8, как и в модели, составляет 16 бит, т. е. каждый регистр может содержать лишь одну инструкцию. Набор инструкций, доступный программисту, представлен в Таблице «Instruction Set Summary» на страницах даташита за номером 202 (ATtiny85) и 311 (ATmega8).

Память данных
Регистры памяти данных обоих МК — 8 битные.
Количество регистров общего назначения — 32 с адресами от 0 по 31 (0×001F). Несмотря на то, что РОН имеют адреса, доступ к ним возможен и непосредственно по именам (r0, r1, r16 и т. д.), что обычно и делается.
Следующие 64 регистра памяти данных с адресами от 32 (0×0020) по 95 (0×005F) — так называемые регистры ввода-вывода (Input/Output Registers), включая регистры периферии и спецрегистры SREG и SP.
С адресацией регистров ввода-вывода AVR существует один нюанс. Адреса, указанные выше (0×0020 — 0×005F) — абсолютные. Сдвинув их на 32 позиции, можно получить относительные адреса — от 0 (0×0000) по 63 (0×003F). Соответственно, предусмотрены два набора инструкций для чтения/записи по абсолютным и относительным адресам регистров ввода-вывода.
Полный перечень регистров ввода-вывода и их адреса (абсолютные или относительные) можно узнать из Таблицы «Register Summary» на страницах 200 (ATtiny85) и 309 (ATmega8) даташита. Отмечу, что для ATtiny85 в указанной таблице приведены лишь относительные адреса регистров, а для ATmega8 — и абсолютные (в скобках), и относительные.
Объём SRAM составляет 512 и 1024 байт для ATtiny85 и ATmega8, соответственно.

Обратите внимание на несколько важных цифр, которые будут использоваться нами впоследствии:
1. Старшие адреса SRAM ATtiny85 и ATmega8 — 0×025F и 0×045F, соответственно. Именно эти значения нам предстоит в первых строках программы записывать в SP для указания вершины стека.
2. Младший адрес памяти программ обоих МК — 0×0000. Начиная с этого адреса будет загружаться в микроконтроллер написанная нами программа.

Выдержки из карт памяти STM32F401 и nRF52832, наряду с Cortex M-4, приведены на Рисунке 32.

Компания ARM, как следует из рисунка, определяет границы блоков памяти (периферии, SRAM и программ), выделив на каждый по 0.5G байтов. Производители же МК на базе ядра ARM (в нашем случае — STMicroelectronics и Nordic Semiconductor), не выходя, обычно, за рамки этих ограничений, определяют стартовый адрес и объём каждого типа памяти, требуемый как для удовлетворения потребностей разработанной ими периферии, так и для эффективной работы всего микроконтроллера в целом.
Адресация регистров всех типов памяти — сквозная.
По аналогии с AVR определим наиболее важные для нас адреса карт памяти.
1. SRAM обоих МК имеет объём 64K байт и начинается с адреса 0×20000000.
2. Младший адрес памяти программ STM32F401 — 0×08000000, а nRF52832 — 0×00000000.

13 регистров общего назначения (r0 — r12), и 4 спецрегистра (указатель стека SP, регистр статуса программы PSR, программный счётчик PC и регистр связи LR, о назначении которого вы узнаете позже) в адресном пространстве не отражены и доступ к ним в программе осуществляется, как и в случае с РОН AVR, непосредственно по именам.

Адреса и наименования регистров периферии приводятся в конце раздела по каждому модулю периферии в «STM32F401 Reference Manual» и «nRF52832 Product Specification».
Набор инструкций для обоих МК можно найти в «Cortex-M4 Generic User Guide» (Раздел 3.1 «Instruction set summary»). Кроме того, для STM32F401 эта информация представлена в Разделе 3 «STM32 Cortex-M4 Programming Manual».
В последующих главах нам пригодится следующая информация касательно инструкций, рассматриваемых в данной работе МК.

Для 32-битных МК на базе ядра ARM предусмотрено два набора инструкций:
1. ARM, длина инструкций которого составляет 32 бита.
2. Thumb с инструкциями длиной 16 бит, призванный минимизировать размер программы после компиляции, а следовательно — объём flash-памяти, требуемой для её размещения.
Микроконтроллеры на базе ядра Cortex M-4, в том числе STM32F401 и nRF52832, используют второй набор — Thumb.

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

Говоря «полный», я имею в виду случай, когда программа содержит участки, написанные как на языке Си, так и на ассемблере.

Давайте, не вникая пока в подробности, рассмотрим этапы процесса.

1. В файле с расширением .c пишется код на языке Си. Чаще всего вспомогательная информация при этом выносится в отдельный, так называемый хидер-файл с расширением .h. Отдельные участки программы, предъявляющие особые требования к скорости работы, плотности кода или таймингу, могут быть написаны на ассемблере (файл с расширением .S).
В реальном проекте файлов каждого типа может быть множество, но это никак не меняет структуру нашей схемы.

2. с— и h-файлы компилируются в ассемблер-файлы. На этом этапе может быть включен и Startup-файл, если он написан на Си и не скомпилирован предварительно. Обычно, Startup-файл содержит код, обеспечивающий подготовительную работу: указание на вершину стека, таблицу векторов прерываний и т. п.

3. Этап ассемблирования. Все имеющиеся файлы с расширением .S преобразуются в объектные файлы с расширением .o.
Опять же, здесь включается Startup-файл, если он написан на ассемблере и предварительно не преобразован в объектный файл.

4. На этом этапе осуществляется компоновка (линковка) всех объектных файлов проекта в единый elf-файл. Помимо созданных в текущем проекте в компоновку могут включаться объектные файлы из других проектов, а также библиотеки (файлы с расширением .a).
Условия компоновки определяются в скрипте с расширением .ld.

5. Полученный в ходе предыдущего этапа elf-файл уже является исполняемым: его используют для отладки — пошаговой проверки работы программы на реальном МК или в симуляторе с целью поиска и устранения ошибок.

6. Происходит окончательное преобразование программы в файл с расширением .hex или .bin, который и загружается в МК (этап 7).

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

▼ dokumentacija-mk.zip  24,26 Mb ⇣ 36
• Программное обеспечение.zip (443.5 Мб) на Облаке Mail.ru

Продолжение следует!
Благодарю за внимание.

Камрад, рассмотри датагорские рекомендации

🌼 Полезные и проверенные железяки, можно брать

Куплено и опробовано читателями или в лаборатории редакции.

 

Программирование AVR и ARM микроконтроллеров в Eclipse. Часть 1 — Схемотехника

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

В случае использования Eclipse CDT среда разработки будет единственная для всех проектов. Это обеспечивается использованием инструментальных средств на базе компилятора GCC под различные целевые платформы.

Небольшое отступление для тех, кто впервые слышит об Eclipse .

Интегрированная среда разработки Eclipse написана на языке программирования Java, для ее работы необходим интерпретатор языка JAVA( виртуальная машина ).

Eclipse является переносимой системой, поскольку интерпретаторы доступны для различных операционных систем. Расширение Elipse возможно благодаря разработке плагинов. Для разных языков программирования существуют свои плагины Eclipse. В плагине Eclipse CDT реализована поддержка разработки программ на языке С( C++, Assembler ).

Для установки Eclipse на персональный компьютер с операционной системой Windows необходимо:

  1. Загрузить виртуальную JAVA-машину с сайта Sun Microsystems по ссылке. Виртуальная машина называется jre, соответственно жмем на кнопку «Download JRE».
  2. Загрузить Eclipse IDE for C/C++ Developers по ссылке.
  3. Установить сначала виртуальную машину jre на компьютер, потом Eclipse. Установка Eclipse сводиться к распаковыванию из архива и копированию каталога Eclipse на жесткий диск.

Для программирования микроконтроллеров AVR и ARM необходимо установить соответствующие инструментальные средства. В качестве таковых для AVR используем пакет WinAVR, для ARM — Sourcery G++.

Чтобы использовать инструментарий под операционную систему Windows для программирования ARM необходимо:

  1. Загрузить IA32 Windows Installer по ссылке.
  2. Запустить программу установки, указать пути для инсталляции пакета программ.

Проверить наличие компилятора в системе после установки можно с помощью команды

arm-none-eabi-gcc — — version

Набрать которую нужно в окне командного интерпретатора( Пуск -> Выполнить… -> cmd ) .

Теперь приступим к установке WinAVR( если он еще не установлен в Вашей системе ). Для этого необходимо загрузить пакет программ WinAVR по ссылке.

После установки пакета WinAVR на Вашем компьютере также установиться текстовый редактор Program Notepad, в котором можна создавать проекты WinAVR.

При работе с Eclipse он нам не понадобиться.

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

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

Создадим два разных каталога для проектов под AVR и ARM микроконтроллеров с такими же названиями. При выборе рабочего пространства для проектов под ARM выбираем путь к каталогу /ARM, точно так же поступим с каталогом /AVR.

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

Начнем с создания в Eclipse пробного проекта для AVR . Для этого закроем окно приглашения «Welcome» и выберем в главном меню File->New->C Project.

В окне «Project type» выбираем тип проекта «Makefile project», пустой проект «Empty project».В окне «Toolchain» выбираем «Other toolchain». В поле «Project name» указываем название нашего пробного проекта, в результате в каталоге рабочего пространства «С:\AVR» появиться подкаталог с названием проекта.

Жмем на кнопку «Finish».

Появиться новый пустой проект с введенным ранее названием. Он пока не содержит файлов с исходниками программы. Будем создавать их постепенно.

В главном меню выбираем «File->New->Source File». В появившемся окне вводим название С-шного файла, в котором будет находиться функция main.

Создадим таким же образом новый заголовочный файл avr_project.h . Для этого в главном меню выбираем «File->New->Header File» и вводим название заголовочного файла.

Интегрированная среда разработки Eclipse имеет множество различных настроек, доступных из графического интерфейса.

Мы почти не будем их использовать, поскольку нам необходимо создать универсальный инструмент. Для этого необходимо использовать Makefile.

Makefile представляет собой управляющий файл для утилиты make. В него можно добавить команды компиляции , компоновки проекта, загрузки бинарного файла в микроконтроллер и т.д.

Писать каждый раз Makefile с нуля вовсе не обязательно, можно использовать заготовку, редактируя ее для различных проектов.

Для того, чтобы создать Makefile кликаем левой клавишей мышки на названии проекта в окне «Project explorer», потом нажимаем правую клавишу для вызова меню. В появившемся контекстном меню выбираем «New->File». В поле «File Name» окна «New File» выбираем название файла «Makefile» и нажимаем клавишу «Finish».

В результате в окне проводника проекта ( Project explorer ) появиться еще один новый файл с названием Makefile.

Заполняем созданный  Makefile следующим содержимым :

.PHONY:    all clean program

CROSS_COMPILE=    avr-
PROJECT_NAME= avr_project
OBJECTS=        $(PROJECT_NAME).o led.o
MCU_TARGET= attiny2313
DEFS=

INC_PATCH=            C:/winavr-20100110/avr/include

CC=             $(CROSS_COMPILE)gcc

CFLAGS=                 -I. -I$(INC_PATCH) -mmcu=$(MCU_TARGET)

LD=                $(CROSS_COMPILE)gcc
LDFLAGS=        -Wl,-Map,$(PROJECT_NAME).map

OBJCOPY=        $(CROSS_COMPILE)objcopy
OBJDUMP=        $(CROSS_COMPILE)objdump

PROG=            $(PROG_PATH)\avreal32
PROG_PATH=        C:\avw125r5
PROG_PORT_NUM    = 1    #LPT port number
PROG_CLOCK        = 0 #clock extern XTAL1
PROG_FUSE_LIST    = CKSEL=4,SUT=2,CKDIV8=0
PROG_FLAGS    =    +$(MCU_TARGET) -p$(PROG_PORT_NUM)    -ap    -o$(PROG_CLOCK)
PROG_WRITE_FLASH    = -e    -v    -c    $(PROJECT_NAME).hex
PROG_WRITE_EEPROM    =    -d\*osccal=0 -d    $(PROJECT_NAME)_eep.hex    -w
PROG_WRITE_FUSE    =    -F$(PROG_FUSE_LIST) -w

program: $(PROJECT_NAME).hex    $(PROJECT_NAME)_eep.hex
$(PROG) $(PROG_FLAGS) $(PROG_WRITE_FLASH) $(PROG_WRITE_EEPROM)    $(PROG_WRITE_FUSE)

all:    $(PROJECT_NAME)

$(PROJECT_NAME): $(OBJECTS)
$(LD) -gdwarf-2 -O2 $(CFLAGS) $(LDFLAGS) -o $(PROJECT_NAME).elf $(OBJECTS)
$(OBJCOPY) -j .text -j .data  -O ihex $(PROJECT_NAME).elf $(PROJECT_NAME).hex
$(OBJCOPY) -j .eeprom —change-section-lma .eeprom=0  -O ihex $(PROJECT_NAME).elf $(PROJECT_NAME)_eep.hex
$(OBJDUMP) -D $(PROJECT_NAME).elf > $(PROJECT_NAME).lst

$(PROJECT_NAME).o: $(PROJECT_NAME).c
$(CC) -gdwarf-2 -O2 $(CFLAGS) -o $(PROJECT_NAME).o -c $(PROJECT_NAME).c

led.o: led.c
$(CC) -gdwarf-2 -O2 $(CFLAGS) -o led.o -c led.c

clean:
rm -f *.o *.hex *.elf *.map *.lst

Обратите внимание, что перед заданием правила необходимо ставить табуляцию( клавиша «Tab»), иначе после попытки собрать проект появиться сообщение об ошибке.

led.o: led.c
<TAB>$(CC) -gdwarf-2 -O2 $(CFLAGS) -o led.o -c led.c

Файлы led.h и led.c включены в проект( скачать ) для демонстрации добавления в Makefile новых  компилируемых файлов . Код проекта  выполняет мерцание светодиодом с частотой 0,5 Гц. Электрическая схема( скачать) очень проста и содержит микроконтроллер attiny2313, разъем PLD-10, светодиод с резистором 330 Ом.

Выполним настройку способа сборки проекта. Для этого заходим в меню «Project» и убираем галочку напротив пункта «Build Automatically». После этого в том же меню «Project» выбираем «Properties», в открывшемся окне выбираем «C/C++ Build ->Settings» и ставим галочку напротив «GNU Elf Parser».

Для сборки проекта в меню «Project» необходимо кликнуть на «Build all» или нажать комбинацию клавиш «Ctrl + B».

При этом Eclipse выполнит команду «make all», тем самым запустит цель «all» из нашего Makefile. Аналогично если кликнуть в меню «Project» на «Clean…», то выполниться цель «clean» из Makefile. В результате последнего действия будут удалены созданные при сборке проекта файлы.

С целями «all» и «clean» ситуация ясна, а вот что делать, если в нашем Makefile есть еще какие-то псевдо цели, которые необходимо выполнить из среды Eclipse?

Например, в нашем Makefile есть цель «Program», предназначенная для запуска внешней утилиты-программатора avreal ( скачать ) и прошивки микроконтроллера.

Для того, чтобы добавить новую цель в Eclipse выберите в контекстном меню проекта пункт «Make Targets» и далее «Build…».

В открывшемся окне «Make targets» необходимо нажать на кнопку «Add» и добавить цель «Program».

Теперь, когда Вам необходимо запрограммировать микроконтроллер, можно сделать это прямо из Eclipse, выбрав в контекстном меню проекта «Make Targets — > Build…», потом выделить необходимую цель ( «Program » ) и нажать на кнопку «Build».

Результаты работы программатора можно наблюдать на вкладке «Console» внизу экрана Eclipse.

Я использовал для программирования микроконтроллера самую простую схему программатора, совместимую с avreal. Это обычный кабель , подключаемый к LPT-порту компьютера. Распайка кабеля тут, адаптер называется «FBPRG».

Также для работы адаптера необходимо установить  драйвера доступа к порту .

На этом знакомство с программированием AVR микроконтроллеров в Eclipse заканчиваем и приступаем к изучению программирования в Eclipse микроконтроллеров ARM . Различия заключаются в основном в структуре проекта для AVR и ARM. Принцип работы в Eclipse такой же.

Программирование микроконтроллеров ARM в Eclipse

Попробую изобразить процесс разработки программ в Eclipse для ARM микроконтроллеров с помощью GNU Tool chain на следующей схеме

Из схемы видно, что исходные файлы на языках С и Assembler компилируются с помощью arm-none-eabi-gcc. Компилятор arm-none-eabi-gcc может осуществлять вызов ассемблера arm-none-eabi-as, компоновщика arm-none-eabi-ld, поэтому в нашем Makefile вместо них будет указан arm-none-eabi-gcc.

В результате компиляции получается один или несколько объектных файлов. Далее компоновщик arm-none-eabi-ld выполняет компоновку объектных модулей в памяти микроконтроллера. Для микроконтроллеров с архитектурой ARM код программы может находиться в разных областях памяти( FLASH, SRAM ).

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

Чтобы написать скрипт компоновки необходимо иметь перед глазами карту памяти используемого микроконтроллера. Для большинства микроконтроллеров ARM можно найти готовый файл сценария.

После компоновки создается один файл исполняемого образа программы в формате elf .

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

Для этого необходимо выполнить преобразование утилитой arm-none-eabi-objcopy в один из доступных для прошивки форматов ( bin , intel hex, motorola S-records и т.д. ).

Из полученного после компоновки elf- файла можно получить листинг кода программы на языке ассемблера с помощью утилиты arm-none-eabi-objdump.

Makefile на нашей схеме изображен отдельно , в нем находиться предписание для утилиты make для сборки всего проекта.

Таким образом , для эффективного программирования ARM с помощью GNU tool chain в Eclipse( равно как и в командной строке ) кроме навыков программирования на языках С и/или Assembler, необходимо также уметь составлять ( редактировать ) Makefile и скрипт компоновки, что не так сложно, как может показаться на первый взгляд.

Долго не мог определиться с аппаратной платформой для демонстрации примеров работы в Eclipse,  поскольку собрать простое устройство на ARM микроконтроллере «на коленке» сложнее из-за  корпусов , применяемых в ARM. Но решение пришло само-собой . Случайно наткнулся в магазине радиодеталей на платку TQFP24-144-05. На эту плату может быть запаяна микросхема в корпусе LQFP с шагом выводом 0,5 мм и количеством выводов от 24 до 144.

Более подробно о макетной плате для изучения ARM микроконтроллеров читайте в моей статье «Самодельная макетная плата для  микроконтроллера STM32F103RBT6».

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

Продолжение следует…

Viewed 31424 times by 5416 viewers

Программирование

ARM — learn.sparkfun.com

Добавлено в избранное Любимый 8

Введение

Внимание! Это руководство было написано для микроконтроллеров ARM с выводами SWD или JTAG. Для подключения к порту вам понадобится специальный программатор (например, J-Link EDU Mini или J-Link EDU Base). Если вы используете микроконтроллер AVR с загрузчиком Arduino с использованием контактов ICSP, вам нужно перейти к Учебник по установке загрузчика Arduino.

SparkFun давно является поклонником Arduino. Мы запрограммировали ATMega328 (а до этого — 168 и 8), написали учебные пособия и взломали всевозможные забавные проекты. Но сейчас рынок созревает, и мы смотрим на гораздо больше чипов ARM. Одним из преимуществ новых микросхем является то, что им обычно не требуется переходник с USB на последовательный порт; вместо этого у них есть встроенный USB (по крайней мере, те, которые мы используем). Вам все равно нужно добавить загрузчик, чтобы использовать их с Arduino, и, поскольку программисты ARM также немного сложнее, чем программисты AVR, вы захотите вложить деньги в отдельного программиста вместо того, чтобы пытаться использовать Uno, который у вас есть.

Обратите внимание: Большинство плат SparkFun предварительно запрограммированы. Это руководство предназначено для предоставления информации, если вы хотите перепрограммировать свою плату или изменить загрузчик.

Несколько плат ARM:

Необходимые материалы

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

Рекомендуемая литература

Если вы не знакомы со следующими концепциями, мы рекомендуем ознакомиться с этими руководствами, прежде чем продолжить.

Основы печатной платы

Что такое печатная плата? В этом руководстве мы разберем, из чего состоит печатная плата, и разберем некоторые общие термины, используемые в мире печатных плат.

Установка загрузчика Arduino

Из этого руководства вы узнаете, что такое загрузчик и почему его нужно устанавливать или переустанавливать. Мы также рассмотрим процесс записи загрузчика, записав шестнадцатеричный файл в микроконтроллер Arduino.

Установка Arduino IDE

Пошаговое руководство по установке и тестированию программного обеспечения Arduino в Windows, Mac и Linux.

Интегральные схемы

Введение в интегральные схемы (ИС). Вездесущие черные фишки электроники. Включает внимание к разнообразию корпусов ИС.

Что такое ARM?

Начнем с того, что такое процессор ARM.Они используются во всем, от Redboard Turbo до Raspberry Pi и большинства мобильных телефонов, но это большой диапазон производительности. ARM — это действительно уникальная бизнес-модель. Arm Holdings выполняет проектные работы для ядер и владеет патентами / авторскими правами / другими юридическими вещами, а затем выдает лицензии на дизайн. Затем ядра вставляются в процессоры, микроконтроллеры, SOC (система на кристалле) и т. Д. Компания может решить, что она хочет создать камеру, которая использует ядро ​​ARM. Они могут лицензировать ядро, максимально повысить энергоэффективность, добавить немного силикона для интерфейса датчика камеры и построить всю систему на чипе.

Если вы посмотрите вокруг, вы действительно увидите довольно много соглашений об именах. Архитектура v7 содержит 3 различных профиля:

  • Cortex-A : профиль приложения
  • Cortex-R : профиль в реальном времени
  • Cortex-M : профиль микроконтроллера

Мы будем смотреть на Cortex-Ms. Cortex M0 / M0 + и M1 на самом деле относятся к архитектуре v6 и могут считаться подмножеством профиля v7.Все это означает, что мы собираемся заняться программированием SamD21 на нашей Redboard Turbo (и других платах), а также SamD51 на Thing Plus. SAMD21 — это ARM Cortex-M0, где SAMD51 — это ARM Cortex-M4F.

Загрузчики

Загрузчик — это небольшой фрагмент кода, который смотрит на порт программирования (в данном случае USB), чтобы узнать, поступает ли новый код. Если есть, то он берет код и помещает его в заранее определенное место.Если нет, то он запускает код, находящийся в данный момент в этом месте.

Большинство плат Arduino имеют загрузчик, который позволяет загружать код через порт USB (или через последовательное соединение UART). Таким образом, после установки загрузчика мы сможем гораздо проще программировать плату. Но иногда мы хотим изменить функцию загрузчика, установить загрузчик на новую плату или просто пропустить загрузчик и установить наш код напрямую (что усложняет другим людям изменение кода, скажем, на коммерческом продукте) .

В качестве загрузчика мы рекомендуем использовать загрузчик UF2. Вы можете перейти сюда для получения дополнительной информации о загрузчиках UF2 или нажать кнопку ниже, чтобы перейти к загрузочным загрузчикам SAMD от SparkFun на GitHub Repo:

Загрузчики SparkFun SamD UF2
UF2 — это формат файла, разработанный Microsoft, который расшифровывается как USB Flashing Format. Этот формат был разработан для PXT (также известного как Microsoft MakeCode) и позволяет программировать платы через Mass Storage Class (съемный диск). Загрузчик также совместим с BOSSA, который используется в Arduino IDE.Другими словами, UF2 позволяет вам писать MakeCode, использовать Circuit Python и использовать Arduino IDE, все в одном загрузчике.

Независимо от того, используете ли вы загрузчик UF2 или другой загрузчик, вам придется загрузить файл. Убедитесь, что загружаемый файл совместим с используемой платой / конфигурацией. Посетите наш репозиторий GitHub для загрузчиков SAMD; с этими платами должен работать загрузчик Turbo (вам нужен файл * .bin ).

JTAG и SWD

Группа совместных испытаний

JTAG обозначает Joint Test Action Group (группа, которая определила стандарт JTAG) и была разработана как способ тестирования плат.JTAG позволяет пользователю общаться с частями микроконтроллера. Во многих случаях это включает в себя предоставление им набора инструкций или программирование платы. Стандарт JTAG определяет 5 контактов:

  • TCK : Тестовые часы
  • TMS : выбор тестового режима
  • TDI : вход тестовых данных
  • TDO : Вывод тестовых данных
  • TRST : тестовый сброс (дополнительно)

Определение JTAG с уменьшенным количеством выводов действительно состоит только из 2 выводов:

  • TMSC : Тестирование последовательных данных
  • TCKS : Тестовые часы

20-контактный разъем, который вы видите на некоторых программаторах, был разработан для JTAG, и все эти дополнительные контакты можно использовать для питания, заземления и других вещей.Хотя JTAG не определяет физическую компоновку контактов, существует несколько общих вариантов. 20-контактный разъем, который вы видите на программаторе Segger J-Link EDU Base и Base Compact, является хорошим примером.

Отладка последовательного кабеля

Serial Wire Debug (SWD) — это просто модификация / реализация JTAG специально для процессоров ARM. SWD помещает 2 контакта (SWDIO и SWCLK) поверх контактов JTAG, позволяя пользователю использовать либо JTAG, либо SWD без необходимости подключать дополнительные контакты.

Программисты и программное обеспечение J-Link

SparkFun теперь содержит 3 разных ARM-программатора от Segger. Если вы только начинаете и не планируете зарабатывать деньги на своем проекте, EDU Mini — отличное место для начала. Если вам нужно что-то более мощное, J-Link Base EDU — хороший вариант. Если вы планируете зарабатывать деньги, вы не можете использовать версии EDU, и в этом случае я рекомендую Base Compact, который мы носим. Это самый дешевый программатор Segger ARM без лицензии EDU.Есть также много высококлассных программистов, но, судя по их цене, вы собираетесь взять их только в том случае, если точно знаете, какие функции вам от них нужны. Но не волнуйтесь, все они более чем способны программировать наши платы.

Сначала загрузите программное обеспечение J-Link. Эта программа хороша для обновления прошивки на программаторах. Идите вперед, откройте конфигуратор Jlink и посмотрите, нужно ли вашему программисту обновление. Пакеты программного обеспечения J-Link имеют множество функций, в которых вы можете углубиться, но мы не собираемся их использовать.Не стесняйтесь экспериментировать и исследовать программное обеспечение и все возможности отладки.

Страница загрузки программного обеспечения J-Link

AVR Студия

Теперь, когда мы все подключили, пора программировать. Есть несколько разных вариантов программирования. Atmel studio — отличный вариант (при условии, что вы используете процессор ATMEL ARM, такой как линейка SAMD). Atmel Studio также позволяет писать программы на C и компилировать код. IDE Arduino также позволяет скомпилировать и загрузить файл *.шестнадцатеричный файл вашего кода. Убедитесь, что вы загрузили и установили Atmel Studio (только для Windows 7 или новее)

Инструкции по установке Atmel Studio 7

Давайте продолжим и откроем Atmel Studio. Затем мы перейдем в Инструменты, а затем в Программирование устройств. В раскрывающемся списке вам нужно будет выбрать своего программатора, а также свое устройство (возможно, сначала вам придется согласиться с Условиями использования). Затем нажмите Применить, и он должен подтвердить вашего программиста. Затем прочтите подпись устройства и целевое напряжение, чтобы убедиться, что все читается правильно.Не стесняйтесь осматриваться, вы можете получить довольно много информации об инструментах, а также информации об устройстве.

Затем мы перейдем на вкладку Memories , вы, вероятно, захотите выбрать «Стереть флэш-память перед программированием», а затем выбрать расположение загрузчика или другого кода. Hit Program, и вы должны быть готовы к работе через секунду или 2.

Трудно видеть? Щелкните изображение, чтобы рассмотреть его поближе.

Поиск и устранение неисправностей

Биты предохранителя для защиты загрузчика

Если вы получаете сообщение об ошибке при попытке программирования, проверьте вкладку «Предохранители».На многих наших платах мы устанавливаем защиту загрузчика от случайной перезаписи. В основном это определяет размер загрузчика. Установка этого значения на 0x07 установит размер загрузчика на 0 и позволит вам писать в это пространство.

Ошибка чтения подписи устройства и мигание

Если вы получаете сообщение об ошибке ниже:

  язык: bash
Ошибка: устройство не обнаружено. Ошибка 4109.

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

Это может быть связано с несколькими причинами:

  • тактовая частота слишком высока
    • попробуйте установить программатор на 1/4 частоты целевого устройства
  • проводка заголовка 2×5 может отличаться в зависимости от вашего программатора
    • проверьте руководство пользователя на программаторе и убедитесь, что распиновка соответствует контактам заголовка цели
    • убедитесь, что паяные соединения в порядке.
  • На целевое устройство
  • не подается питание
    • , поскольку программатор не обеспечивает питание, убедитесь, что вы обеспечиваете питание целевого устройства.

В данном конкретном случае это произошло из-за подключения заголовка 2×5 к порту Atmel JTAGICE3.Он отличался от заголовка 2×5 на целевом устройстве. Последняя версия Atmel JTAGICE имеет два порта и адаптер для правильного подключения к разъему 2×5.

Ресурсы и дальнейшее развитие

Нужна дополнительная информация? Ознакомьтесь с некоторыми ссылками ниже:

Ознакомьтесь с другими замечательными руководствами для плат на базе ARM от SparkFun:

SAMD21 Mini / Dev Breakout Руководство по подключению

Знакомство с микропроцессором Atmel ATSAMD21G18 и коммутационными платами Mini и Pro R3.Повысьте свои навыки Arduino с помощью мощного процессора ARM Cortex M0 +.

9DoF Razor IMU M0 Руководство по подключению

Как использовать и перепрограммировать 9DoF Razor IMU M0, комбинацию микропроцессора ATSAMD21 ARM Cortex-M0 и MPU-9250 9DoF-in-a-chip.

RedBoard Turbo Руководство по подключению

Знакомство с RedBoard Turbo. Повысьте свои навыки Arduino с помощью мощного процессора SAMD21 ARM Cortex M0 +!

SAMD51 Thing Plus Руководство по подключению

В этом руководстве рассматриваются основные функции SAMD51 Thing Plus и освещаются функции новой платы разработки ARM Cortex-M4F.

(БЕСПЛАТНО) Создайте прошивку с нуля, используя язык сборки ARM. Введение в программирование сборки ARM Cortex-M | от Исследователя истины

Изучите практическое программирование на ассемблере. Сборка прошивки с нуля с использованием языка сборки ARM

https://www.udemy.com/course/arm-cortex-m-assembly-programming/

  1. Твердое владение набором инструкций ARM.

2. напишите полное программное обеспечение для сборки на основе архитектуры ARM Cortex-M

  • Средой разработки для этого курса является Keil uVision 5, которую можно бесплатно загрузить с веб-сайта ARM.
  • Наш выбор микроконтроллера низкий стоимость TM4c123H6PM Tiva C LaunchPad от Texas Intruments
  • Предполагается, что предварительные знания в области разработки встроенных систем отсутствуют.

Этот курс не предполагает предварительных знаний программирования на ассемблере. Все, что требуется от студентов, — это любопытство. Курс охватывает архитектуру набора инструкций ARM, синтаксис сборки и программирование, а также предоставляет дополнительные главы по введению в ARM Cortex-M. Основная цель этого курса — предоставить учащимся практические навыки и прочную основу, на которой они смогут начать создавать хорошо написанный код с хорошим сочетанием ассемблера и C.

  • Студенты встраиваемых систем
  • Специалисты в области встраиваемых систем
  • Любители

Прутви Бхупал

Курс четко определен и организован.Это помогает понять основы и позволяет двигаться дальше. Очень признателен за создание веб-сайта и добавление всех сопутствующих материалов для этого курса. С нетерпением жду новых курсов от вас. Большое спасибо.

Инженер по встроенным микропрограммам

  • 4.2 Рейтинг преподавателя
  • 7 574 отзыва
  • 53072 студентов
  • 41 Курс

Меня зовут Израиль, я занимаюсь исследованиями и работаю в области встроенных систем более 7 лет.На Udemy я обучил десятки тысяч студентов встроенным системам, уделяя особое внимание таким темам, как программирование сборки, проектирование операционных систем в реальном времени, разработка микропрограмм и цифровая обработка сигналов. Я могу преподавать эти темы, потому что в своей повседневной работе я применяю концепции из этих тем.

Присоединяйтесь к одному из моих курсов и посмотрите, как все пройдет. Вы всегда можете запросить возврат.

Вы также можете проверить мой блог: cortex -m dot com

[РАСКРЫТИЕ: этот пост содержит партнерские ссылки, то есть, когда вы нажимаете на ссылки и делаете покупку, вы получаете комиссию.]

Программирование встраиваемых систем на процессоре ARM Cortex-M3 / M4

Самые продаваемые разработчики курсов по программированию микроконтроллеров и RTOS, имеющие более 45 000 активных студентов и команду соучредителей, которые помогут вам в вашем путешествии по программированию встраиваемых систем.

Мы опубликовали курсы по встроенному C, программированию микроконтроллеров, программированию RTOS, встроенному Linux и разработке драйверов устройств Linux.

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

Запишитесь на созданные нами курсы, и мы надеемся, что вы не будете разочарованы .

Что мы делаем?

Мы используем возможности Интернета, чтобы у вас под рукой были онлайн-курсы в области встраиваемых систем и программирования, микроконтроллеров, операционных систем реального времени, разработки микропрограмм, встроенного Linux и драйверов устройств. Спасибо Удеми.

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

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

Попробуйте наши курсы, и мы уверены, что они действительно заставят вас почувствовать, что вы сделали правильный выбор.

Мы верим в РЕАЛЬНЫХ РАБОТ , которые решают РЕАЛЬНЫХ ПРОБЛЕМЫ наших клиентов.

Прочтите полные обзоры, чтобы узнать больше о курсах.

==> Порядок изучения курсов FastBit Embedded Brain Academy <==

Если вы новичок в области встраиваемых систем, вы можете пройти наши курсы в указанном ниже порядке.

Это всего лишь рекомендация инструктора для начинающих.

1) Программирование на встроенном C микроконтроллера: абсолютный новичок (Embedded C)

2) Программирование встроенных систем на процессоре ARM Cortex-M3 / M4 (для процессора ARM Cortex M4)

3) Освоение микроконтроллера со встроенным драйвером Разработка (MCU1)

4) Мастеринг микроконтроллера: ТАЙМЕРЫ, ШИМ, CAN, RTC, НИЗКАЯ МОЩНОСТЬ ( MCU2)

5) Освоение RTOS: практическое использование FreeRTOS и STM32Fx с отладкой (RTOS)

6) Демистификация программирования DMA микроконтроллера ARM Cortex M (DMA)

7) Разработка нестандартного загрузчика микроконтроллера STM32Fx (загрузчик)

8) Встроенный Linux Шаг за шагом с использованием Beaglebone Black (Linux) *

it

— это онлайн-подразделение по обучению встроенному программному обеспечению компании Bharati Software

Обучение на базе ARM с нуля 2-базовые концепции

Обучение ARM с нуля с нуля 2 основных концепции

См. Полное собрание работ Zhu Youpeng ARM без покрытия

1.Составные характеристики и направление развития встраиваемых систем

(1) Выделенное программное и аппаратное обеспечение можно настроить и настроить

(2) Низкое энергопотребление, высокая надежность и стабильность

(3) Код программы короткий и лаконичный

(4) Код можно закрепить (код можно записать в прошивку)

(5) Реальное время: Реальное время встроенной системы очень требовательно, UCOS

(6) Слабая интерактивность, многие студенты любят играть с сенсорным экраном, но на самом деле это не основное направление встроенного

.

(7) Профессиональные разработчики

2.Состав встраиваемой системы

(1) Аппаратное обеспечение

Микропроцессор: CPU

Память: храните данные, необходимые вашей программе для обработки

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

(2) Программное обеспечение: (Встроенное программное обеспечение и программное обеспечение MCU не являются слоями)

Встроенная операционная система: (в основном написано) драйвер фактически записывает операционную систему

BSP: пакет поддержки платы Комплект для разработки на уровне платы (программное обеспечение для поддержки оборудования)

заявка:

заявка:

Программирование приложений операционной системы и сетевое программирование

GUI GPRS 3G Wi-Fi

Операционная система Интеллектуальная операционная система Операционная платформа

Аппаратное ПЗУ, ОЗУ, порт ввода-вывода

Общая функция слишком сложная, без наслоения сложно обойтись.

Программирование между приложением и операционной системой.

Люди, которых можно использовать, не обязательно могут быть созданы, поэтому писать драйверы сложнее

3. Развитие встраиваемых систем 1:

(1) С одним чипом в качестве ядра наличие программируемого контроллера

— Операционная система не поддерживается

— ПО в основном собрано

— Однофункциональный, низкая эффективность обработки, небольшой контейнер для хранения, без внешнего интерфейса

— Простота использования, низкая цена

(2) На основе встроенного ЦП и простой операционной системы в качестве ядра

— Несколько типов ЦП, слабая универсальность

— Низкие накладные расходы системы и высокая эффективность

— достижение определенной степени совместимости и масштабируемости

— Пользовательский опыт невысокий, а интерактивный интерфейс недостаточно дружелюбен

(3) Помечено встроенной операционной системой

— Хорошая совместимость, применима к разным платформам

— Низкие системные издержки, высокая эффективность, высокая модульность и масштабируемость

— Графический интерфейс, удобный интерфейс

— Богатые внешние интерфейсы

(4) Отмечено Интернетом вещей

— Интеграция сенсорной технологии, Интернет-технологий и традиционных встроенных технологий

— Маленькая модель, интеллектуальная, объединенная в сеть и визуализированная

— Низкое энергопотребление, охрана окружающей среды

— Многоядерная технология, технология облачных вычислений и технология виртуализации

DSP (основная операция) плюс ARM (основное управление)

4.Что такое кросс-компиляция?

Встроенная кросс-компиляция.

Два режима проявления:

(1) Невстроенная разработка:

Чистая разработка программного обеспечения может осуществляться прямо на компьютере.

(2) Встроенная разработка:

Исполняемая программа компилируется и выпускается для процессоров низкого уровня, таких как платы разработки. Этот метод называется кросс-компиляцией.

ЦП для встраиваемой разработки относительно прост и не может создать среду разработки сам по себе, а некоторые даже не имеют операционной системы.Кросс-компиляция может быть разработана на высокопроизводительных машинах для низкопроизводительных машин

программное обеспечение.

Каковы характеристики кросс-компиляции?

Кросс-компиляция должна использовать специальную цепочку инструментов кросс-компиляции

Поскольку исполняемая программа не может быть запущена локально, она должна быть согласована с определенными средствами

(выделенный отладчик, отладчик JTAG, загрузка через USB, загрузка через последовательный порт, загрузка с SD-карты, общий доступ к сети)

Загрузите исполняемую программу на целевое встроенное устройство для запуска и отладки)

5.Принцип построения ЦП, шины данных и адресной шины

(SMP: симметричный многоядерный процессор)

Схема ЦП и шины


Анализ изображения:

1. Есть CPU и UART вообще SOC

Регистр: данные, передаваемые через FLASH, отображаются в соответствующий регистр, и ЦП может работать

Контроллер: выполните логическое управление

Калькулятор

: сложение, вычитание, умножение и деление

2.Шина: канал передачи данных

2.1, разделенный на адресную шину и шину данных

CPU передает данные по адресной шине

Отделение адресной шины от данных предназначено для быстрой передачи данных, а блок хранения делится на блоки.

Число бит адресной шины определяет диапазон адресации ЦП:

Количество битов шины данных определяет единичный обмен данными ЦП

3.DDR: рабочая память

4. FLASH: эквивалент жесткого диска компьютера

будьте осторожны:

1. Количество разрядов шины адреса ЦП и шины данных может быть разным

Типичным представителем является 51 однокристальный микрокомпьютер (хотя шина данных 8-битная, но адресная шина 16-битная), но в целом тот же

2. Количество бит ЦП относится к количеству шин данных

3. Диапазон адресации 32-битного процессора — 4G, поэтому 32-битная память лучше, поэтому для программирования лучше использовать int.

Компиляция в сборку с нуля

Компиляция в сборку с нуля

Купить электронную книгу • $ 45

Итак, вы пытались узнать, как работают компиляторы и языки программирования?

Возможно, вы узнали о компиляции на JavaScript или о создании интерпретатора? Или, может быть, о компиляции в байт-код? Всем хороших шагов.

Но напряжение нарастает.

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

Эта электронная книга подробно покажет вам, как можно создать компилятор с нуля, который идет от исходного кода до сборки .

Код примера написан в подмножестве TypeScript , который читается как псевдокод. В книге описана конструкция и реализация компилятора, который испускает 32-битные инструкции сборки ARM . Все, что вам нужно знать, это как программировать, книга научит вас достаточно теории компиляторов и программированию на ассемблере, чтобы начать работу.

Купите сейчас и получите следующее:

Почему ARM?

Во многих смыслах набор инструкций ARM — это то, что делает эту книгу возможной.

По сравнению с Intel x86-64, набор команд ARM является произведением искусства.

Intel x86-64 является результатом эволюции от 8-битного процессора к 16-битному, затем к 32-битному и, наконец, к 64-битному. На каждом этапе эволюции он накапливал сложность и беспорядок. На каждом этапе он пытался удовлетворить противоречивые требования.

  • Intel x86-64 основан на архитектуре комплексного набора команд (CISC), которая изначально была оптимизирована для написания ассемблера вручную.
  • ARM, с другой стороны, основана на архитектуре сокращенного набора команд (RISC), которая оптимизирована для написания компиляторов.

Угадайте, какая из них является более легкой целью для компилятора?

Если бы эта книга была ориентирована на Intel x86-64 вместо ARM, она была бы в два раза длиннее и, что более вероятно, никогда не была написана. Кроме того, поставив 160 миллиардов устройств, нам лучше привыкнуть к тому факту, что сегодня ARM является доминирующей архитектурой с набором команд.

Другими словами… ARM — хорошее начало. Изучив его, вы будете лучше подготовлены для перехода на x86-64 или новый ARM64.

Сможете ли вы запустить код, созданный вашим компилятором?

Готов поспорить, ты будешь! Приложение содержит множество способов выполнения кода ARM, начиная с Raspberry Pi, облачной виртуальной машины, и заканчивая эмуляцией ARM в Linux и Windows.

Почему именно TypeScript?

Прежде всего, вы сможете читать эту книгу на любом подходящем языке программирования.Мне было сложно выбрать кого-то для этой работы, и я рад, что выбрал TypeScript.

TypeScript, вероятно, никому не нравится, но это хороший компромисс:

  • Вы переходите с динамического языка, такого как JavaScript, Python или Ruby? Тогда, если вы закроете глаза на аннотации типов, TypeScript — это просто современный JavaScript.
  • Если вы переходите с Java или C #, вы будете чувствовать себя как дома, поскольку TypeScript предоставлен вам теми же людьми, которые принесли вам C # (и Turbo Pascal!) .

Не волнуйтесь, если вы никогда раньше не видели кода TypeScript. Если вы сможете прочитать следующее, вы, скорее всего, сможете это понять, так как в книге идет (настоящий код из книги здесь!) :

  class Label {
  статический счетчик = 0;
  значение: число; // Тип аннотации

  constructor () {
    this.value = Label.counter ++;
  }

  нанизывать() {
    return '.L' + this.value;
  }
}  

Я избегал использования в коде каких-либо функций языка TypeScript или JavaScript.

Если вы работаете со статически типизированными языками функционального программирования (Haskell, OCaml или Reason ML), вы обнаружите, что структура классов, которую я использовал, хорошо преобразована в алгебраический тип данных. Собственно, именно так я написал это вначале.

Содержание книги

Книга состоит из двух частей. Часть I представляет собой подробное , пошаговое руководство о том, как разработать небольшой «базовый» компилятор, который может компилировать простые программы для сборки ARM.

К концу части I у вас будет работающий компилятор, способный компилировать простые функции, подобные этой:

  function factorial (n) {
  if (n == 0) {
    возврат 1;
  } еще {
    вернуть n * факториал (n - 1);
  }
}  

В код сборки ARM, например:

 .глобальный факториал
факториал:
  нажмите {fp, lr}
  mov fp, sp
  нажмите {r0, r1}
  ldr r0, = 0
  нажмите {r0, ip}
  ldr r0, [fp, # -8]
  поп {r1, ip}
  cmp r0, r1
  moveq r0, # 1
  movne r0, # 0
  cmp r0, # 0
  beq .L1
  ldr r0, = 1
  b .L2
.L1:
  ldr r0, = 1
  mov r1, r0
  ldr r0, [fp, # -8]
  sub r0, r0, r1
  bl факториал
  mov r1, r0
  ldr r0, [fp, # -8]
  муль r0, r0, r1
.L2:
  mov sp, fp
  pop {fp, pc}  

Этот код не получит никаких наград, и оптимизирующий компилятор мог бы добиться большего, но это только начало!

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



Прочитать отрывок

Печатное издание?

На данный момент нет печатного издания. Но будет. Однако для этого пока нет графика. Печать немного сложнее, чем цифровая. Мне нужно быть на 100% уверенным в каждом слове в книге, прежде чем оно будет отправлено в печать. Однако я знаю, что никому не нравится покупать одну и ту же книгу дважды. Итак, если вы купите электронную книгу сегодня, я обещаю дать вам скидку, как только выйдет печатное издание.

Не можете себе это позволить?

Если по обстоятельствам вы не можете позволить себе купить книгу — напишите мне письмо на [email protected], и я уверен, что мы что-нибудь придумаем!

Обо мне

Меня зовут Владимир Келешев, я работал с компиляторами как коммерчески, так и с открытым кодом. Моя страсть к сборке ARM проистекает из моей предыдущей работы со встроенными системами. В настоящее время я работаю в сфере финансов с предметными языками.

Вопросы?

Свяжитесь со мной vladimir @ keleshev.com или в Твиттере на @keleshev.


Иллюстрации: @PbKatiuska

Запись сборки ARM (часть 1)

Добро пожаловать в эту серию руководств по основам сборки ARM. Это подготовка к следующей серии руководств по разработке эксплойтов для ARM. Прежде чем мы сможем погрузиться в создание шелл-кода ARM и построение цепочек ROP, нам нужно сначала осветить некоторые основы сборки ARM.

Пошагово будут рассмотрены следующие темы:

Учебное пособие по основам сборки ARM

:
Часть 1: Введение в сборку ARM
Часть 2: Регистры типов данных
Часть 3: Набор инструкций ARM
Часть 4: Инструкции памяти: Загрузка и сохранение данных
Часть 5: Загрузка и сохранение нескольких частей
6: Условное выполнение и ветвление
Часть 7: Стек и функции

Чтобы следовать примерам, вам понадобится лабораторная среда на базе ARM.Если у вас нет устройства ARM (например, Raspberry Pi), вы можете настроить свою собственную лабораторную среду на виртуальной машине с помощью QEMU и дистрибутива Raspberry Pi, следуя этому руководству. Если вы не знакомы с базовой отладкой с помощью GDB, вы можете получить основы в этом руководстве. В этом руководстве основное внимание будет уделено 32-разрядной версии ARM, а примеры скомпилированы на ARMv6.

Почему ARM?

Это руководство обычно предназначено для людей, которые хотят изучить основы сборки ARM. Специально для тех из вас, кто интересуется написанием эксплойтов на платформе ARM.Возможно, вы уже заметили, что процессоры ARM повсюду вокруг вас. Когда я оглядываюсь вокруг, я могу насчитать в моем доме гораздо больше устройств с процессором ARM, чем процессоры Intel. Сюда входят телефоны, маршрутизаторы и, не говоря уже об устройствах Интернета вещей, продажи которых в наши дни, похоже, стремительно растут. Тем не менее, процессор ARM стал одним из самых распространенных ядер ЦП в мире. Это подводит нас к тому факту, что, как и ПК, устройства IoT подвержены неправильным злоупотреблениям при проверке ввода, таким как переполнение буфера.Учитывая широкое использование устройств на базе ARM и возможность неправильного использования, атаки на эти устройства стали гораздо более распространенными.

Тем не менее, у нас больше экспертов, специализирующихся на исследованиях безопасности x86, чем по ARM, хотя язык ассемблера ARM, пожалуй, самый простой из широко распространенных языков ассемблера. Итак, почему все больше людей не уделяют внимания ARM? Возможно, потому, что существует больше учебных ресурсов, посвященных эксплуатации на Intel, чем на ARM. Подумайте о великолепных руководствах по Intel x86 Exploit, написанных Fuzzy Security или Corelan Team — подобные руководства помогают людям, интересующимся этой конкретной областью, получить практические знания и вдохновение для изучения, помимо того, что описано в этих руководствах.Если вы заинтересованы в написании эксплойтов для x86, учебники Corelan и Fuzzysec станут вашей идеальной отправной точкой. В этой серии руководств мы сосредоточимся на основах сборки и написании эксплойтов на ARM.

Процессор

ARM против процессора Intel

Между Intel и ARM много различий, но главное отличие — это набор команд. Intel — это процессор CISC (Compstruction Set Computing), который имеет более крупный и многофункциональный набор инструкций и позволяет многим сложным инструкциям обращаться к памяти.Поэтому у него больше операций, режимов адресации, но меньше регистров, чем у ARM. Процессоры CISC в основном используются на обычных ПК, рабочих станциях и серверах.

ARM является процессором RISC (вычисление с сокращенным набором инструкций) и поэтому имеет упрощенный набор инструкций (100 инструкций или меньше) и регистры более общего назначения, чем CISC. В отличие от Intel, ARM использует инструкции, которые работают только с регистрами, и использует модель памяти Load / Store для доступа к памяти, что означает, что только инструкции Load / Store могут обращаться к памяти.Это означает, что для увеличения 32-битного значения по определенному адресу памяти на ARM потребуется три типа инструкций (загрузка, увеличение и сохранение), чтобы сначала загрузить значение по определенному адресу в регистр, увеличить его в регистре и сохранить это обратно в память из реестра.

Уменьшенный набор команд имеет свои достоинства и недостатки. Одним из преимуществ является то, что инструкции могут выполняться быстрее, потенциально обеспечивая большую скорость (системы RISC сокращают время выполнения за счет сокращения тактовых циклов на инструкцию).Обратной стороной является то, что меньшее количество инструкций означает больший акцент на эффективном написании программного обеспечения с ограниченными доступными инструкциями. Также важно отметить, что ARM имеет два режима: режим ARM и режим Thumb. Инструкции Thumb могут быть 2 или 4 байтами (подробнее об этом в Части 3: Набор инструкций ARM).

Еще больше различий между ARM и x86:

  • В ARM большинство инструкций можно использовать для условного выполнения.
  • Процессоры Intel серии x86 и x86-64 используют формат с прямым порядком байтов
  • Архитектура ARM была прямым порядком байтов до версии 3.С тех пор процессоры ARM превратились в с порядком байтов от бита до и имеют настройку, которая позволяет переключать с порядком байтов от до .

Есть различия не только между Intel и ARM, но и между разными версиями ARM. Эта серия руководств призвана сделать ее как можно более общей, чтобы вы получили общее представление о том, как работает ARM. Как только вы поймете основы, легко узнать нюансы для выбранной вами целевой версии ARM. Примеры в этом руководстве были созданы на 32-битной ARMv6 (Raspberry Pi 1), поэтому пояснения относятся именно к этой версии.

Названия различных версий ARM также могут сбивать с толку:

Семейство ARM ARM архитектура
ARM7 ARM v4
ARM9 ARM v5
ARM11 ARM v6
Cortex-A ARM v7-A
Cortex-R ARM v7-R
Cortex-M АРМ v7-M

Прежде чем мы сможем погрузиться в разработку эксплойтов для ARM, нам сначала нужно понять основы программирования на языке ассемблера, для чего требуются некоторые базовые знания, прежде чем вы начнете ценить его.Но зачем нам вообще сборка ARM, разве недостаточно писать эксплойты на «нормальном» языке программирования / сценариев? Это не так, если мы хотим иметь возможность выполнять обратный инжиниринг и понимать программный поток двоичных файлов ARM, создавать собственный шелл-код ARM, создавать цепочки ARM ROP и отлаживать приложения ARM.

Вам не нужно знать каждую мелочь о языке ассемблера, чтобы иметь возможность выполнять обратный инжиниринг и разработку эксплойтов, но некоторые из них необходимы для понимания более широкой картины.Основы будут рассмотрены в этой серии руководств. Если вы хотите узнать больше, вы можете посетить ссылки, перечисленные в конце этой главы.

Так что же такое ассемблер? Язык ассемблера — это просто тонкий слой синтаксиса поверх машинного кода, который состоит из инструкций, закодированных в двоичных представлениях (машинный код), что и понимает наш компьютер. Так почему бы вместо этого просто не написать машинный код? Что ж, это было бы занозой в заднице. По этой причине мы напишем сборку ARM, которая намного проще для понимания людьми.Наш компьютер не может запускать ассемблерный код сам, потому что ему нужен машинный код. Инструмент, который мы будем использовать для сборки ассемблерного кода в машинный код, — это GNU Assembler из проекта GNU Binutils с именем as , который работает с исходными файлами с расширением * .s.

После того, как вы написали файл сборки с расширением * .s, вам нужно собрать его с помощью as и связать с ld:

 $ как program.s -o program.o
$ ld program.o -o программа 

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

1110 0001 1010 0000 0010 0000 0000 0001

Пока все хорошо, но мы не можем вспомнить, что означает каждый из этих шаблонов (0 и 1). По этой причине мы используем так называемую мнемонику, аббревиатуры, чтобы помочь нам запомнить эти двоичные шаблоны, где каждой инструкции машинного кода дается имя. Эти мнемоники часто состоят из трех букв, но это не обязательно. Мы можем написать программу, используя эту мнемонику в качестве инструкций.Эта программа называется программой на языке ассемблера, а набор мнемоник, который используется для представления машинного кода компьютера, называется языком ассемблера этого компьютера. Следовательно, язык ассемблера — это самый низкий уровень, используемый людьми для программирования компьютера. Операнды инструкции идут после мнемоники. Вот пример:

MOV R2, R1

Теперь, когда мы знаем, что программа сборки состоит из текстовой информации, называемой мнемоникой, нам нужно преобразовать ее в машинный код.Как упоминалось выше, в случае сборки ARM проект GNU Binutils предоставляет нам инструмент под названием как . Процесс использования ассемблера, такого как как , для преобразования из языка ассемблера (ARM) в машинный код (ARM) называется сборкой.

Таким образом, мы узнали, что компьютеры понимают (реагируют) на наличие или отсутствие напряжений (сигналов) и что мы можем представлять несколько сигналов в последовательности нулей и единиц (битов). Мы можем использовать машинный код (последовательности сигналов), чтобы заставить компьютер реагировать определенным образом.Поскольку мы не можем вспомнить, что означают все эти последовательности, мы даем им сокращения — мнемоники и используем их для представления инструкций. Этот набор мнемоник является языком ассемблера компьютера, и мы используем программу под названием Assembler для преобразования кода из мнемонического представления в машиночитаемый машинный код так же, как это делает компилятор для языков высокого уровня.

Hiwonder xArm2.0 Интеллектуальная роботизированная рука с поддержкой Scratch и обучающий программируемый робот на Python — Oz Robotics

ПОЛИТИКА ОБМЕНА: Oz Robotics хочет, чтобы вы остались довольны своей новой покупкой.Однако мы соблюдаем политику обмена наших поставщиков, потому что мы не производим эти продукты, а наши поставщики. Пожалуйста, ознакомьтесь с политикой обмена продуктами, которая определяется каждым поставщиком для их собственных перечисленных продуктов, которые можно найти на вкладке Доставка на каждой странице продукта. После того, как вы использовали продукт, мы и наш поставщик (-ы) имеем право не возвращать деньги, но они предложат обмен на неправильно приобретенные товары или товары, которые имеют серьезные и необратимые дефекты или технические проблемы.В случае ошибочно приобретенных продуктов или любых других подобных проблем, стоимость доставки будет оплачена покупателем. Если приобретенный вами продукт неисправен, отправьте нам электронное письмо по адресу [email protected] с фотографиями или видео дефектных деталей, чтобы мы могли оценить их перед отправкой. Щелкните ЗДЕСЬ, чтобы узнать больше о политиках Exchange.

ВОЗВРАТ / ВОЗВРАТ: Oz Robotics принимает возврат в очень ограниченном количестве, если только нет производственного брака. Для любых электронных предметов возврат принимается только на устройствах, которые имеют серьезные и необратимые проблемы с качеством, при этом покупатель должен подать заявку на возврат в течение 7 дней с даты доставки.Перед принятием возмещения, пожалуйста, приложите изображения или видео, а также любые другие материальные доказательства дефекта. Однако мы соблюдаем политику обмена наших поставщиков, потому что мы не производим эти продукты, а наши поставщики.

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

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

Если вы хотите вернуть товар, сделайте это в течение 7 дней с даты отгрузки, чтобы получить возмещение стоимости покупки за вычетом доставки и обработки.Возврат будет зачислен на использованную исходную кредитную карту для оплаты в течение 24-48 ЧАСОВ после получения продукта обратно. Мы будем взимать 70% комиссии за пополнение запасов.

После того, как ваш возврат будет получен и проверен, и, если будет достигнута договоренность о возмещении, возврат будет зачислен на исходную кредитную карту, использованную для оплаты, в течение 24-48 часов. Обратите внимание, что мы взимаем 20% комиссию за возврат, если вы хотите вернуть товар, не имеющий дефектов.

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

Не возвращайте товар в наш офис в Нью-Йорке. В случае обмена или возврата, пожалуйста, сначала напишите нам по адресу support@ozrobotics.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *