SREG — регистр состояния AVR
Каждая арифметическая команда AVR оставляет след в восьми битах регистра SREG: был ли перенос, ноль ли результат, отрицательный ли он. По этим флагам работают условные переходы, а старший бит — глобальное разрешение прерываний.
Обновлено Редакция GAW
SREG (Status Register) — восьмибитный регистр состояния ядра AVR. Его биты отражают результат последней арифметической или логической команды, и условные переходы проверяют их без отдельной команды сравнения; старший бит управляет прерываниями. Регистр лежит в пространстве ввода-вывода по адресу 0x3F (0x5F в адресах памяти данных), все биты доступны на чтение и запись, после сброса равны нулю (DS40002061B, разд. 7.3.1).
Флаги
| Бит | Флаг | Значение |
|---|---|---|
| 7 | I | глобальное разрешение прерываний |
| 6 | T | хранение бита для команд BST и BLD |
| 5 | H | полуперенос из бита 3 — для двоично-десятичной арифметики |
| 4 | S | знак: S = N ⊕ V |
| 3 | V | переполнение в дополнительном коде |
| 2 | N | отрицательный результат — старший бит |
| 1 | Z | нулевой результат |
| 0 | C | перенос из старшего бита |
Флаги обновляет каждая команда АЛУ — какие именно, указано в описании команды в AVR Instruction Set Manual. Например, ADC (сложение с переносом) меняет H, S, V, N, Z и C, и пара add r2,r0 / adc r3,r1 складывает 16-битные числа: перенос младших байтов попадает в старшие через флаг C (DS40002198B, разд. 6.1).
Условные переходы
| Сравнение | Знаковое | Беззнаковое |
|---|---|---|
| больше или равно | BRGE: S = 0 | BRSH: C = 0 |
| меньше | BRLT: S = 1 | BRLO: C = 1 |
| равно / не равно | BREQ: Z = 1 / BRNE: Z = 0 | те же |
По разд. 4 DS40002198B. Для знаковых чисел проверяют S, а не N: при переполнении старший бит результата врёт, а S его исправляет. Для многобайтного сравнения служит CPC — у него флаг Z не устанавливается, а только сохраняется, если результат ноль: после цепочки CP, CPC, CPC флаг Z равен единице, только если совпали все байты.
Флаг I и прерывания
При входе в прерывание аппаратура сбрасывает флаг I, а команда RETI снова его устанавливает, поэтому обработчики по умолчанию не вкладываются друг в друга. Команды SEI и CLI ставят и снимают флаг программно. После CLI прерывания запрещены сразу, а после SEI следующая команда выполняется раньше любого ожидающего прерывания — на этом построены пары «SEI; SLEEP» (разд. 7.7).
Сам SREG при входе в прерывание не сохраняется. Компилятор C сохраняет его в прологе обработчика, а при написании на ассемблере это делают вручную. Тот же приём — основа критической секции: копию SREG делают до CLI и записывают обратно в конце, чтобы вернуть флаг I в прежнее состояние:
uint8_t sreg = SREG; /* save the I flag */
cli();
/* timed sequence or shared data */
SREG = sreg; /* restore, do not force sei() */
Набор команд, которые меняют флаги, и их длительности собраны в статье «Система команд AVR», устройство ядра и регистрового файла — в статье «Архитектура AVR».
Частые вопросы
Нужно ли сохранять SREG в обработчике прерывания?
Да, если обработчик меняет флаги: по даташиту ATmega328P регистр состояния не сохраняется автоматически при входе в прерывание и не восстанавливается при выходе. Компилятор C делает это сам в прологе и эпилоге обработчика, а на ассемблере сохранение — обязанность программиста. Иначе прерывание, пришедшее между сравнением и условным переходом, испортит флаги основной программы.
Чем флаг S отличается от флага N?
N — просто старший бит результата. S — это N, исправленный на переполнение: S = N ⊕ V. Если вычитание двух знаковых чисел переполнило 8 бит, старший бит результата неверен, а S всё равно показывает правильный знак разности. Поэтому знаковые переходы BRGE и BRLT проверяют именно S.
Почему для сохранения флага I копируют весь SREG, а не вызывают SEI в конце?
Потому что секция может выполняться и при уже запрещённых прерываниях — например, внутри другой критической секции. Копия SREG до CLI и запись её обратно возвращают флаг I в прежнее состояние, каким бы оно ни было. Так сделан пример с записью EEPROM в даташите ATmega328P.
Источники
- Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P megaAVR Data Sheet (DS40002061B, 2020) — разд. 7.3: регистр состояния содержит сведения о результате последней арифметической команды, обновляется после всех операций АЛУ, что часто избавляет от отдельных команд сравнения; не сохраняется автоматически при входе в прерывание и не восстанавливается при возврате — это делает программа; разд. 7.3.1: адрес 0x3F (0x5F), все биты чтение-запись, начальное значение 0; бит 7 I — глобальное разрешение прерываний, сбрасывается аппаратно при входе в прерывание и устанавливается командой RETI, управляется командами SEI и CLI; бит 6 T — хранение бита для BLD и BST; бит 5 H — полуперенос, полезен в двоично-десятичной арифметике; бит 4 S = N ⊕ V; бит 3 V — переполнение в дополнительном коде; бит 2 N — отрицательный результат; бит 1 Z — нулевой результат; бит 0 C — перенос; разд. 7.7: после CLI прерывания запрещены немедленно, после SEI следующая команда выполняется раньше ожидающих прерываний; пример сохранения SREG вокруг временной последовательности записи EEPROM (in r16, SREG; cli; …; out SREG, r16); разд. 7.7.1: реакция на прерывание — не меньше четырёх тактов
- Microchip. AVR Instruction Set Manual (DS40002198B, 2021) — разд. 4 Conditional Branch Summary: BRGE (Rd ≥ Rr) — S = 0, BRLT — S = 1, знаковые; BRSH — C = 0, BRLO — C = 1, беззнаковые; BRNE — Z = 0, BREQ — Z = 1; BRCC/BRCS, BRPL/BRMI, BRVC/BRVS — простые проверки C, N, V; флаги — результат предыдущей команды, после CP, CPI, SUB, SUBI переход соответствует столбцу Common Test; разд. 6.1 ADC: H — перенос из бита 3, V — переполнение в дополнительном коде, N = R7, Z — результат 0x00, C — перенос из старшего бита, пример add r2,r0 / adc r3,r1 для 16-битного сложения; разд. 6.46 CPC: флаг Z сохраняет прежнее значение, если результат ноль, и сбрасывается иначе
Нашли ошибку?
Смотрите также
- Флаг переноса (C)Перенос из старшего разряда и заём при вычитании
- Флаг переполнения (V)Выход знакового результата за диапазон
- Критическая секцияУчасток кода под запретом прерываний
- Система команд AVRВсе инструкции с флагами и тактами, адресация, примеры кода
- Архитектура AVRЯдро, конвейер, память, порты, прерывания, сброс, такты и сон