Перейти к содержанию

Архитектура микроконтроллеров AVR

Микроконтроллер AVR — это 8-битное RISC-ядро с раздельными памятью программ и памятью данных, 32 рабочими регистрами и периферией, которая видна как регистры ввода-вывода. Разбираем по даташиту ATmega328P, как устроены ядро и конвейер, три адресных пространства, порты, прерывания, сброс, тактирование и режимы сна — то общее, что есть у классических ATmega и ATtiny.

Обновлено Редакция GAW

AVR — семейство 8-битных микроконтроллеров Atmel, которое теперь выпускает Microchip. В классических ATmega и ATtiny одно и то же ядро и одинаковое устройство памяти, прерываний и портов; отличаются объём памяти, набор периферии и корпуса. Здесь всё разобрано на примере ATmega328P из Arduino Uno и Nano — с адресами и цифрами из его даташита.

Коротко

  • Ядро: гарвардская архитектура, конвейер на одну команду, 32 рабочих регистра — до 1 MIPS на 1 МГц.
  • Память ATmega328P: флеш 32 КБ (16K слов), SRAM 2 КБ, EEPROM 1 КБ — три отдельных адресных пространства.
  • Периферия: 64 регистра ввода-вывода (команды IN, OUT, SBI, CBI) и 160 регистров расширенного ввода-вывода.
  • Прерывания: 26 векторов в начале флеш-памяти; чем меньше адрес, тем выше приоритет; реакция — от 4 тактов.
  • Запуск: с завода — внутренний генератор 8 МГц, делённый на 8, то есть 1 МГц.

Гарвардская архитектура и конвейер

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

Конвейер ядра AVR: выборка следующей команды идёт одновременно с выполнением текущейЧетыре такта T1–T4. В такте T1 выбирается команда 1, в T2 она выполняется, а команда 2 выбирается, и так далее: каждый такт завершается одна команда.T1T2T3T4Команда 1выборкавыполнениеКоманда 2выборкавыполнениеКоманда 3выборкавыполнениеКоманда 4выборкаВыполнение: операнды из регистров → АЛУ → запись результата, один такт
Конвейер AVR: в каждом такте выбирается следующая команда и выполняется текущая (по рисунку 7-4 даташита ATmega328P).

Тактовая частота ядра не делится внутри: на 16 МГц AVR выполняет до 16 миллионов простых команд в секунду. Большинство команд — 16-битные, четыре занимают два слова: JMP, CALL, LDS и STS. Обращение к SRAM занимает 2 такта, переходы и вызовы — 2–4 такта. Число тактов каждой команды — в статье «Система команд AVR».

Рабочие регистры

У ядра 32 восьмибитных рабочих регистра r0–r31, и почти все команды работают с ними напрямую. АЛУ берёт операнды из регистров и туда же пишет результат — память данных для арифметики не нужна. Шесть старших регистров образуют три 16-битных указателя: X (r27:r26), Y (r29:r28) и Z (r31:r30). Ими адресуют память данных — с автоинкрементом, автодекрементом и смещением до 63 байт от Y и Z, а указатель Z ещё и читает константы из флеш-памяти командой LPM.

Регистры отображены на первые 32 адреса памяти данных, хотя физически это не ячейки SRAM. Результат операций АЛУ отражается во флагах регистра состояния SREG: перенос, ноль, знак, переполнение и другие. Схема регистров, флаги SREG и режимы адресации подробно разобраны в статье «Система команд AVR».

Три адресных пространства

Флеш-память программ

У ATmega328P 32 КБ флеш-памяти. Все команды AVR — по 16 или 32 бита, поэтому память организована 16-битными словами: 16K слов с адресами 0x0000–0x3FFF, а счётчик команд PC — 14-битный. В начале памяти — таблица векторов сброса и прерываний, в конце — загрузочная секция, размер которой задают фьюзы BOOTSZ. Только код из загрузочной секции может перезаписывать флеш командой SPM, на этом основаны загрузчики вроде загрузчика Arduino.

Память программ ATmega328P: векторы прерываний, секция приложения и загрузочная секция16K слов по 16 бит, адреса 0x0000–0x3FFF. С адреса 0x0000 — 26 векторов по два слова (0x0000–0x0033), дальше — секция приложения, в конце — загрузочная секция размером 256, 512, 1024 или 2048 слов по фьюзам BOOTSZ. Масштаб не соблюдён.адрес слова26 векторовRESET, INT0, … SPM_READYСекция приложенияпрограмма и константыЗагрузочная секциязагрузчик, команда SPM0x00000x00340x3F000x3FFFBOOTSZ → начало и размер11: 0x3F00, 256 слов (Arduino Uno)10: 0x3E00, 512 слов01: 0x3C00, 1024 слов (Arduino Nano)00: 0x3800, 2048 словСлово — 16 бит: 32 КБ флеш-памяти = 16K слов. Масштаб не соблюдён.
Флеш-память ATmega328P: 26 векторов по два слова, секция приложения и загрузочная секция. Её начало задают фьюзы BOOTSZ (таблица 27-13 даташита); у Arduino Uno — 256 слов, у Nano — 1024.

Флеш-память выдерживает не меньше 10 000 циклов записи и стирания. Константные таблицы можно размещать в любой её части и читать командой LPM.

Память данных

Память данных ATmega328P — 2304 адреса подряд, от 0x0000 до 0x08FF:

АдресаЧто тамКак обращаться
0x0000–0x001F32 рабочих регистра r0–r31любые команды с регистрами
0x0020–0x005F64 регистра ввода-выводаIN, OUT по адресам 0x00–0x3F; биты первых 32 — SBI, CBI, SBIS, SBIC
0x0060–0x00FF160 регистров расширенного ввода-выводатолько LD, LDS, LDD, ST, STS, STD
0x0100–0x08FF2048 байт SRAMпеременные и стек

Пять режимов адресации — прямой, косвенный, косвенный со смещением, с предекрементом и с постинкрементом — достают до всего этого пространства. Доступ к SRAM занимает два такта.

EEPROM

EEPROM — отдельное пространство в 1 КБ, которое не входит ни в память программ, ни в память данных. К нему обращаются через регистры ввода-вывода EEAR (адрес), EEDR (данные) и EECR (управление). Запись байта длится около 3,3 мс и выдерживает не меньше 100 000 циклов; на время чтения ядро останавливается на 4 такта, на время запуска записи — на 2. Чтобы случайно не испортить данные, запись требует последовательности: сначала бит EEMPE, затем в течение четырёх тактов — EEPE. При пониженном питании EEPROM портится, поэтому даташит советует держать микроконтроллер в сбросе с помощью детектора пониженного питания (BOD).

Порты и регистры ввода-вывода

Вся периферия AVR — порты, таймеры, USART, SPI, АЦП — управляется регистрами в пространстве ввода-вывода. Каждый порт описывают три регистра: DDRx задаёт направление (1 — выход), PORTx — уровень выхода или включение подтягивающего резистора у входа, PINx — читает уровень на выводах. Запись единицы в бит PINx переключает соответствующий бит PORTx — так вывод инвертируют одной командой.

Регистры портов B, C и D у ATmega328P лежат в первых 32 адресах пространства ввода-вывода, поэтому отдельный бит меняют командами SBI и CBI за два такта без риска затереть соседние биты. Регистры таймеров, АЦП и USART в основном находятся в расширенном пространстве — к ним обращаются командами LDS и STS. Как номера выводов Arduino соответствуют портам и битам, показывает карта выводов Arduino.

Стек

Стек — область в конце SRAM, которая растёт к младшим адресам. Указатель стека SP — пара регистров SPH:SPL в пространстве ввода-вывода; у ATmega328P после сброса он уже равен последнему адресу SRAM (0x08FF). PUSH уменьшает SP на 1, вызов подпрограммы или прерывание кладут в стек адрес возврата — 2 байта при 16-битном счётчике команд и 3 байта у кристаллов с флеш-памятью больше 128 КБ, например ATmega2560. Стек и переменные делят одну и ту же SRAM: глубокая рекурсия или большой локальный массив могут незаметно затереть глобальные данные.

Прерывания

Таблица векторов занимает начало флеш-памяти: у ATmega328P это 26 векторов по два слова — сброс, внешние прерывания INT0 и INT1, прерывания по изменению уровня, сторожевой таймер, таймеры, SPI, USART, АЦП, EEPROM, компаратор, TWI и SPM. В векторе обычно стоит переход к обработчику. Приоритет определяется адресом: чем меньше адрес вектора, тем выше приоритет; самый высокий — у сброса, следом — INT0.

Чтобы прерывание сработало, нужно установить его собственный бит разрешения и общий флаг I в SREG (команда SEI). Когда прерывание принимается:

  1. Аппаратно сбрасывается флаг I — вложенные прерывания запрещены, пока программа сама их не разрешит.
  2. Не меньше чем за 4 такта счётчик команд сохраняется в стек, затем выполняется команда вектора — переход за 3 такта.
  3. Флаг прерывания, по которому оно пришло, обычно сбрасывается аппаратно.
  4. Команда RETI за 4 такта возвращает адрес из стека и снова устанавливает флаг I.

Регистр SREG аппаратно не сохраняется — это задача обработчика. После возврата ядро обязательно выполнит одну команду основной программы, прежде чем принять следующее прерывание. Если прерывание пришло, когда оно было запрещено, флаг запоминает событие, и обработчик вызовется после разрешения. Векторы можно перенести в начало загрузочной секции битом IVSEL регистра MCUCR — это нужно загрузчику, который пользуется прерываниями.

Сброс и запуск

ATmega328P сбрасывают четыре источника:

  • включение питания — напряжение ниже порога сброса при включении;
  • внешний сброс — низкий уровень на выводе RESET дольше минимальной длительности;
  • сторожевой таймер — истёк его период в режиме сброса системы;
  • детектор пониженного питания — напряжение ниже порога BOD, если детектор включён.

При сбросе выводы сразу переходят в начальное состояние (входы без подтяжки) — даже без тактового сигнала. Когда все источники сброса отпускают, внутренний счётчик ещё удерживает сброс, пока стабилизируется питание и запускается генератор; длительность задержки выбирают фьюзы SUT и CKSEL. Затем выполнение начинается с вектора сброса по адресу 0x0000 или, если запрограммирован фьюз BOOTRST, с начала загрузочной секции.

Тактирование

Источник тактового сигнала выбирают фьюзы CKSEL:

ИсточникCKSEL3…0
Кварц, экономичный генератор1111–1000
Кварц, генератор с полным размахом0111–0110
Часовой кварц 32,768 кГц0101–0100
Внутренний генератор 128 кГц0011
Калиброванный RC-генератор 8 МГц0010
Внешний тактовый сигнал0000

С завода выбран внутренний RC-генератор 8 МГц и запрограммирован фьюз CKDIV8, поэтому новый ATmega328P работает на 1 МГц. Делитель системной частоты можно поменять и из программы регистром CLKPR — от 1 до 256. Значения фьюзов для своего источника удобно подобрать в калькуляторе фьюзов AVR.

Режимы сна

Шесть режимов сна выключают разные части микроконтроллера: Idle, ADC Noise Reduction, Power-down, Power-save, Standby и Extended Standby. Режим выбирают биты SM2–SM0 регистра SMCR, разрешают битом SE, а входят в сон командой SLEEP. Разрешённое прерывание будит микроконтроллер: после 4 тактов и времени запуска генератора выполняется обработчик, а затем — команда после SLEEP. Содержимое регистров и SRAM во сне сохраняется. Кроме сна, ток снижают регистром PRR — он отключает тактирование неиспользуемой периферии.

Классические AVR и новые серии

Всё сказанное относится к классическим ATmega и ATtiny. У XMEGA и у новых серий с ядром AVRxt — tinyAVR 0/1/2, megaAVR 0, AVR Dx и Ex — устройство другое: контроллер прерываний с уровнями приоритета, другие интерфейсы программирования (PDI у XMEGA, UPDI у AVRxt), а у AVRxt флеш-память ещё и видна в общем адресном пространстве данных. Различия ядер и наборов команд сведены в статье «Система команд AVR», а обзор семейств — в разделе «Микроконтроллеры AVR».

Частые вопросы

Почему AVR выполняет команду за один такт?

У AVR гарвардская архитектура: память программ и память данных подключены к ядру разными шинами, поэтому следующая команда выбирается из флеш-памяти, пока выполняется текущая. А операнды берутся из 32 рабочих регистров, к которым есть доступ за один такт: чтение двух регистров, операция в АЛУ и запись результата укладываются в такт. Отсюда до 1 миллиона команд в секунду на каждый мегагерц. Команды, которые обращаются к SRAM или переходят по адресу, занимают 2–4 такта.

Сколько памяти у ATmega328P и как она устроена?

Три независимых адресных пространства. Флеш-память программ — 32 КБ, организована как 16K слов по 16 бит, адреса слов 0x0000–0x3FFF. Память данных — адреса 0x0000–0x08FF: 32 рабочих регистра, 64 регистра ввода-вывода, 160 регистров расширенного ввода-вывода и 2048 байт SRAM. EEPROM — отдельные 1024 байта, к которым обращаются через регистры EEAR, EEDR и EECR.

Сколько тактов проходит от прерывания до обработчика?

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

Сохраняет ли AVR регистр SREG при прерывании?

Нет. Аппаратно в стек попадает только адрес возврата, а флаг I в SREG сбрасывается, чтобы запретить вложенные прерывания. Если обработчик меняет флаги, он должен сам сохранить SREG и восстановить его перед RETI; компилятор avr-gcc делает это в функциях с ISR() автоматически.

На какой частоте работает новый ATmega328P?

На 1 МГц: с завода выбран внутренний RC-генератор 8 МГц и запрограммирован фьюз CKDIV8, который делит частоту на 8. Чтобы работать на 8 МГц, снимают CKDIV8 или пишут делитель в регистр CLKPR из программы; для кварца меняют фьюзы CKSEL и SUT. Частоту и фьюзы можно подобрать в калькуляторе фьюзов AVR.

Сколько раз можно перезаписать флеш и EEPROM AVR?

По даташиту ATmega328P — не меньше 10 000 циклов записи и стирания для флеш-памяти и не меньше 100 000 для EEPROM. Запись байта EEPROM длится около 3,3 мс, и всё это время новую запись начинать нельзя. Для данных, которые меняются часто, например счётчиков, запись распределяют по разным ячейкам.

Источники

  1. Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet, DS40002061B — 7 — ядро: гарвардская архитектура, конвейер, регистры, указатели X, Y, Z, стек, время реакции на прерывание; 8 — флеш, SRAM, EEPROM, карта памяти данных, время записи EEPROM; 9 — источники тактирования, заводская настройка; 10 — режимы сна; 11 — источники сброса; 12 — таблица векторов; 14 — порты; 27 — размеры загрузочной секции
  2. Microchip. AVR Instruction Set Manual, DS40002198C — форматы команд, такты, работа со стеком на кристаллах с 22-битным счётчиком команд

Нашли ошибку?