Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

КР1 / 78

.docx
Скачиваний:
4
Добавлен:
08.04.2022
Размер:
825.91 Кб
Скачать

7. Виды памяти микроконтроллеров (на примере семейства AVR). Стек и его инициализация.

Организация памяти. В микроконтроллерах семейства AVR реализована Гарвардская архитектура, в соответствии с которой разделены не только адресные пространства памяти программ и данных, но также и шины доступа к ним. Способы адресации и доступа к этим областям памяти также различны. Такая структура позволяет центральному процессору работать одновременно как с памятью программ, так и с памятью данных, что существенно увеличивает производительность. Каждая из областей данных (ОЗУ и энергозависимая ERROM) также расположена в своем адресном пространстве.

Память пространств предназначена для хранения команд, управляющих функционированием микроконтроллера. Память программ также часто используется для хранения таблиц констант, не меняющихся во время работы программы. Память программ представляет собой электрически стираемое программируемое постоянное запоминающее устройство (ППЗУ, FLASH ПЗУ). В связи с тем, что длина всех команд кратна одному слову (16 бит), память программ имеет 16-разрядную организацию. Логически память программ разделена на две неравные части: область прикладной программы и область загрузчика. В последней может располагаться специальная программа (тот самй загрузчик), позволяющая микроконтроллеру самостоятельно управлять загрузкой и выгрузкой прикладных программ. Если же возможность самопрограммирования микроконтроллера не используется, прикладная программа может располагаться и в области загрузчика. Для адресации памяти программ используется счетчик команд. Размер счетчика команд составляет 12…16 разрядов, в зависимости от объема адресуемой памяти.

Обобщенная карта памяти AVR МК:

По адресу 0х0000 памяти программ находится вектор сброса. После инициализации (сброса) МК выполнение программы начинается с этого адреса. Начиная с адреса 0х0001 или 0х0002 памяти программ располагается таблица векторов прерываний. При возникновении прерывания, после сохранения в стеке текущего значения счетчика команд, происходит выполнение команды, расположенной по адресу соответствующего вектора. Поэтому по этим адресам располагаются команды перехода к подпрограммам обработки прерываний. В моделях с объемом памяти менее 8 Кбайт в качестве этих команд используются команды относительного перехода (RJMP), а в остальных моделях – команды абсолютного перехода (JMP).

В качестве промежуточных операндов используется 32 ячейки – оперативные регистры общего назначения (РОН). Доступ к этим ячейкам самый быстрый, а число операций с их содержимым наиболее разнообразное. При написании программ на языке ассемблера эти регистры обозначаются как R0, R1, R2… R31, и делятся на три группы:

  1. Младшие R0-R15 – обычные РОН, но в некотором смысле неполноценные. С ними не работают многие команды, например, загрузка непосредтственного числа.

  2. Старшие R16-R31 – полноценные регистры, работающие со всеми командами без исключения.

  3. Индексные R26…R31 – 6 последних регистров из старшей группы отличаются от остальных. В принципе, их можно использовать и как обычные РОН. Но, кроме этого, они могут образовывать регистровые пары X(R26:R27), Y(R28:R29), Z(R30:R31), которые используются как укащатели при работе с памятью.

Память данных. Память данных AVR МК разделена на три части: регистровая память, оперативная память (статическое ОЗУ) и энергозависимое ЭСППЗУ (EEPROM).

Регистровая память включает 32 РОН, объединенных в файл, и служебные регистры ввода/вывода (РВВ). В старших моделях МК имеется также область дополнительных (Extended) регистров ввода/вывода (ДРВВ). Под РВВ в памяти МК отводятся 64 байта, а под ДРВВ – 160 байт. Введение ДРВВ связано с тем, что для поддержки периферийных устройств этих моделей обычных 64 регистров недостаточно. В обеих областях РВВ располагаются различные служебные регистры (регистры управления МК, регистры состояния), а также регистры управления периферийными устройствами, входящими в состав МК. Распределение адресов пространства ввода/вывода (как основного, так и дополнительного) зависит от конкретной модели МК и входящих в его структуру периферийных устройсвтв.

Кроме 32 РОН в структуру МК обычно включена оперативная память (ОЗУ), предназначенная для временного хранения переменных. Есть она не везде – в самых младших МК семейства Tiny оперативной памяти нет вовсе, в ее качестве выступают 32 РОН. Оперативная память представляет собой несколько сотен ячеек для временного хранения данных, от 64 байт до 4 килобайт, в зависимости от модели. В этих ячейках могут храниться любые данные, а доступ к ним осуществляется через команды LOAD и STORE.

Для долговременного хранения различной информации, которая может изменяться в процессе функционирования готовой системы (калибровочные константы, серийные номера, ключи), в МК может использоваться энергозависимая EEPROM-память. ЕЕ объем составляет для различных моделей от 512 байт до 4 Кбайт. Эта память расположена в отдельном адресном пространстве, а доступ к ней осуществляется с помощью РВВ.

Стек. Стек представляет собой область памяти, которую микроконтроллерное ядро использует для сохранения и восстановления адресов возврата и подпрограмм прерываний. Практически у всех МК AVR стек размещается в оперативной памяти. Для адресации текущего элемента (вершины стека) используется указатель стека SP (Stack Pinter). Это однобайтовый РВВ SPL у моделей с объёмом памяти данных до 256 байт, или двухбайтовые SPH:SPL (SPH – старший байт, SPL – младший байт) у старших моделей с большим объемом памяти.

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

При возврате подпрограммы этот адрес извлекается из стека и загружается в счетчик команд. Значение указателя стека соответственно увеличивается на два. То же происходит и во время вызова прерываний.

Схематическое расположение стека в памяти данных:

Во всех моделях AVR МК стек доступен со стороны пользовательской программы и может быть использован в процессе выполнения программы. Для работы со стеком существует всего две команды: занесение в стек (PUSH) и извлечение из стека (POP).

При старте МК обычно первым делом проводят инициализацию стека, записывая в 16-битный регистр SP адрес, откуда он будет увеличиваться. Делается это следующим образом:

LDI R16, Low(RAMEND)

OUT SPL, R16

LDI R16, High(RAMEND)

OUT SPH, R16

RAMEND – это макроопределение, указывающее на конец ОЗУ для каждого конкретного МК. При написании программ на языках более высокого уровня (C, C++) компилятор проводит эту операцию самостоятельно, без участия пользователя.

8. Прерывания, вектор прерываний.

Прерывания – это аппаратные события, которые прекращают нормальный ход программы для выполнения какой-либо приоритетной задачи. При этом событие может быть как внутренним (от встроенной периферии самого микроконтроллера – таймеров, портов ввода-вывода, АЦП и других), так и внешним – например, появление на входе импульса от нажатой кнопки. Возникает вопрос, можно ли обрабатывать эти события без использования прерываний?

В наиболее простых случаях так и происходит: основная программа представляет собой бесконечный цикл, внутри которого тем или иным способом отслеживаются возникновения событий, при наступлении которых устанавливается определённое значение переменной, называемой обычно флагом (бит в специализированном регистре или ячейке памяти). Основная программа проверяет в цикле значения используемых флагов, и при их изменении переходит к обработке соответствующего события. Чем неудобен подобный подход? Во-первых, подобный цикл ожидания полностью загружает микроконтроллер, который в это время мог бы делать что-нибудь полезное. Во-вторых, некоторые события в принципе не могут долго ждать, например, обработка приёма данных по USART – если пропустить хоть один байт, логика работы программы будет нарушена, а повторная пересылка данных может быть не предусмотрена. Именно поэтому для организации более эффективного использования ресурсов микроконтроллера и используют прерывания.

Как работают прерывания. При возникновении прерывания микроконтроллер завершает текущую команду, сохраняет в стеке содержимое счетчика команд и совершает переход на адрес соответствующего вектора прерывания. По этому адресу, как правило, находится команда безусловного (JMP или RJMP) перехода к подпрограмме обработки прерывания. За каждым аппаратным прерыванием микроконтроллера закреплен свой адрес, и все вместе они образуют таблицу векторов прерываний, которая расположена в самом начале памяти программ. Поскольку у каждого микроконтроллера набор периферии разный, вектор прерываний также будет отличаться. Ниже приведена таблица векторов прерываний микроконтроллера ATTiny2313, который мы будем использовать вынуждены использовать в новых условиях при выполнении практических работ.

Таблица векторов прерываний микроконтроллера ATTiny2313

Адрес

Источник прерывания

Описание

1

.ORG 0x0000

RESET

External Pin, Power-on Reset

2

.ORG 0x0001

INT0

External Interrupt Request 0

3

.ORG 0x0002

INT1

External Interrupt Request 1

4

.ORG 0x0003

TIMER1 CAPT

Timer/Counter1 Capture Event

5

.ORG 0x0004

TIMER1 COMPA

Timer/Counter1 Compare Match A

6

.ORG 0x0005

TIMER1 OVF

Timer/Counter1 Overflow

7

.ORG 0x0006

TIMER0 OVF

Timer/Counter0 Overflow

8

.ORG 0x0007

USART0, RX

USART0, Rx Complete

9

.ORG 0x0008

USART0, UDRE

USART0 Data Register Empty

10

.ORG 0x0009

USART0, TX

USART0, Tx Complete

11

.ORG 0x000A

ANALOG COMP

Analog Comparator

12

.ORG 0x000B

PCINT

Pin Change Interrupt

13

.ORG 0x000C

TIMER1 COMPB

Timer/Counter1 Compare Match B

14

.ORG 0x000D

TIMER0 COMPA

Timer/Counter0 Compare Match A

15

.ORG 0x000E

TIMER0 COMPB

Timer/Counter0 Compare Match B

16

.ORG 0x000F

USI START

USI Start Condition

17

.ORG 0x0010

USI OVERFLOW

USI Overflow

18

.ORG 0x0011

EE READY

EEPROM Ready

19

.ORG 0x0012

WDT OVERFLOW

Watchdog Timer Overflow

.ORG INT_VECTORS_SIZE

Конец таблицы прерываний

Контроллер стартует с адреса 0x00 (нулевого адреса памяти программ). Далее мы делаем безусловный переход на метку RESET. Если этого не сделать, то контроллер начнёт выполнять команды из таблицы векторов прерываний, что нам совершенно не нужно. После перехода по метке первым делом необходимо проинициализировать стек. Потом, используя команду SEI, разрешаем глобальные прерывания. За разрешение конкретных прерываний для каждого вида периферии отвечают соответствующие регистры управления локальными прерываниями.

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

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

Для глобального разрешения или запрещения прерываний предназначен флаг I регистра состояния SREG. Для разрешения работы прерываний он должен быть установлен в единицу (это делается с помощью ассемблерной команды SEI), а для запрещения сброшен (командой CLI). По умолчанию (после сброса микроконтроллера) этот флаг сброшен, и все прерывания микроконтроллера запрещены. Также возможно индивидуальное разрешение или запрещение (маскирование) прерываний, которое производится установкой или сбросом соответствующих разрядов регистров масок прерываний. Для каждого блока периферии существует собственный регистр для разрешения локальных прерываний. При возникновении прерывания флаг I регистра SREG сбрасывается на аппаратном уровне, запрещая тем самым обработку следующих прерываний. При возврате из подпрограммы обработки прерывания (при выполнении команды RETI) флаг I устанавливается обратно.

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

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

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

Поскольку прерывание нарушает стандартный ход выполнения программы и может возникнуть в любой момент времени, необходимо сохранить текущие данные. Для этого необходимо использовать стек, туда нужно переместить все регистры, используемые в обработчике прерывания, чтобы не потерять хранящиеся там данные. Также необходимо сохранять регистр флагов SREG, в котором хранится результат логических операций:

TIM0_OVF:

PUSH         R16            // Сохраняем регистр R16

IN R16, SREG     // Перемещаем содержимое SREG в R16

PUSH         R16            // Сохраняем всё в стек

PUSH         R17            // R17 сохраняем туда же

……………           // Выполнение кода обработчика прерывания

POP  R17            // Перед выходом из прерывания извлекаем

POP  R16            // сохранённые данные

OUT SREG, R16 // Действуем при этом в обратном порядке

POP  R16

RETI                   // Выходим из прерывания

Также существует ряд операций, которые должны выполняться неразрывно, например, чтение 16-разрядного счетного регистра таймера. Поскольку ядро микроконтроллеров семейства Tiny 8-разрядное, то 16-разрядный регистр таймера считывается (или записывается) в два приема – причём сначала считывается младший байт, а потом старший (это подробно рассматривалось в главе, посвящённой таймерам). Между двумя этими операциями не должно возникать никаких прерываний, поэтому перед чтением такого регистра необходимо их запретить, а после окончания операции чтения разрешить обратно.

Соседние файлы в папке КР1