6.4.1.6 Атрибуты функций AVR
Бэкенд AVR поддерживает следующие атрибуты функций:
-
signal interrupt-
Функция является обработчиком прерывания (ISR). Если указан один из этих атрибутов, компилятор генерирует последовательности входа в функцию и выхода из неё, подходящие для использования в обработчике прерывания.
Аппаратное обеспечение AVR глобально отключает прерывания при обработке прерывания.
- ISR с атрибутом
signalне включают прерывания повторно. В обработчикеsignalбезопасно включать прерывания. Эта «безопасность» относится только к коду, сгенерированному компилятором, а не к схеме IRQ приложения, за которую отвечает само приложение. - ISR с атрибутом
interruptвключают прерывания повторно. Первая инструкция процедуры — это инструкцияSEI, которая глобально включает прерывания.
Рекомендуется использовать эти атрибуты с помощью макроса
ISR, предоставляемогоavr/interrupt.hиз AVR-LibC:#include <avr/interrupt.h> ISR (INT0_vect) // Uses the "signal" attribute. { // Code } ISR (ADC_vect, ISR_NOBLOCK) // Uses the "interrupt" attribute. { // Code }Если для одной и той же функции указаны оба атрибута —
signalиinterrupt, — тоsignalигнорируется без предупреждения. - ISR с атрибутом
-
signal(num) interrupt(num)-
Подобен атрибуту
signalилиinterruptбез аргумента, но номер IRQ передаётся атрибуту в качестве аргумента num, вместо того чтобы указывать имя ISR в качестве имени функции:__attribute__((signal(1))) static void my_handler (void) { // Code for __vector_1 }Обратите внимание, что функция-обработчик не обязана быть видимой извне. Рекомендуется использовать эти атрибуты с помощью макроса
ISR_N, предоставляемогоavr/interrupt.hиз AVR-LibC:#include <avr/interrupt.h> ISR_N (PCINT0_vect_num) static void my_pcint0_handler (void) { // Code } ISR_N (ADC_vect_num, ISR_NOBLOCK) static void my_adc_handler (void) { // Code }Атрибут
ISR_Nможно указывать несколько раз; в этом случае несколько векторов прерываний будут указывать на одну и ту же функцию-обработчик. Это аналогично макросуISR_ALIASOFиз AVR-LibC, но без дополнительных затрат, вызванныхISR_ALIASOF. -
noblock -
Этот атрибут можно использовать вместе с атрибутом
signal, чтобы указать, что обработчик прерывания должен начинаться с инструкцииSEI, глобально включающей прерывания. Совместное использование атрибутовsignalиnoblockдаёт тот же эффект, что и атрибутinterrupt. Использование атрибутаnoblockбезsignalне даёт эффекта. -
naked -
Этот атрибут позволяет компилятору сформировать необходимое объявление функции, оставляя её тело на языке ассемблера. Для указанной функции компилятор не генерирует последовательности пролога и эпилога. В функциях с атрибутом naked безопасно использовать только базовые инструкции
asm(см. раздел Базовый Asm — инструкции ассемблера без операндов). Хотя расширенныйasmили сочетание базовогоasmс кодом на C могут, на первый взгляд, работать, полагаться на их надёжную работу нельзя; такая возможность не поддерживается. -
no_gccisr -
Не используйте
__gcc_isr— псевдоинструкцию — в функции с атрибутомinterruptилиsignal, то есть в обработчике прерывания (ISR). Используйте этот атрибут, если пролог ISR всегда должен начинаться с такого кода:push __zero_reg__ push __tmp_reg__ in __tmp_reg__, __SREG__ push __tmp_reg__ clr __zero_reg__
и, соответственно, эпилог всегда должен завершаться таким кодом — независимо от того, используются ли в ISR упомянутые регистры. Этот атрибут может быть полезен, например, в следующих случаях:
- Код, который (фактически) изменяет биты
SREG, отличные от флагаI, посредством записи в ячейку памятиSREG. - Код, в котором встроенный ассемблер используется для перехода к другой функции, ожидающей наличия (части) описанного выше кода пролога.
Чтобы отключить генерацию
__gcc_isrдля всего модуля компиляции, используйте параметр -mno-gas-isr-prologues; см. раздел Параметры AVR. - Код, который (фактически) изменяет биты
-
OS_main OS_task-
В AVR функции с атрибутом
OS_mainилиOS_taskне сохраняют и не восстанавливают регистры, сохраняемые при вызове, в прологе и эпилоге.Атрибут
OS_mainможно использовать, если гарантируется, что на момент входа в функцию прерывания отключены. Это позволяет сэкономить ресурсы, когда для выделения кадра под локальные переменные необходимо изменить указатель стека.Атрибут
OS_taskможно использовать, если на момент входа в функцию не гарантируется, что прерывания отключены, например в функциях задач многопоточной операционной системы. В этом случае изменение регистра указателя стека защищено сохранением, сбросом и восстановлением глобального флага разрешения прерываний.Отличия от атрибута функции
naked:-
Функции
nakedне содержат инструкции возврата, тогда как функцииOS_mainиOS_taskсодержат инструкцию возвратаRETилиRETI. -
Функции
nakedне создают кадр для локальных переменных и не используют указатель кадра, тогда как функцииOS_mainиOS_taskделают это при необходимости.
-
Функции
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/AVR-Function-Attributes.html