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

Соглашения по регистрам

Вижу, что в документе Cortex-M3 programming manual написано - при входе в прерывание сохраняется

● R0-R3, R12

● Return address

● PSR

● LR

Добавление __attribute__((__interrupt__)) (как я смог понять из кода) добавляет выравнивание стека на 8. В этом нет необходимости - обработка прерывания процессором это обеспечивает независимо от требования на выравнивание.

А что обеспечивает сохранение остальных регистров? Или эти регистры в gcc 4.7.2 в случае их использования в вычислениях сохраняются автоматически?

Сейчас при невнимательном тестировании на первый взгляд всё работает и без __attribute__((__interrupt__)).

 

В документе http://gcc.gnu.org/onlinedocs/gcc-4.7.2/gc...tion-Attributes написано только то, что я и понял - на Cortex Mx только выравнивает стэк:

On ARMv7-M the interrupt type is ignored, and the attribute means the function may be called with a word aligned stack pointer.

В start-up никаких изменений режима работы процессора не делается.

static void ResetException( void )
{

   uint32_t * pSrc, * pDest ;


   /* Low level Initialize */
arm_cpu_initialize();		// watchdog disable, clock initialize

   /* Initialize the relocate segment */
   pSrc = & _sidata;
   pDest = & __data_start;

   if ( pSrc != pDest )
   {
	// compiled for FLASH
       for ( ; pDest < & __data_end ; )
       {
           *pDest++ = *pSrc++ ;
       }
   }
// Следить, чтобы переменные не оказались в стеке, очищаемом сейчас.
// Для этого, например, использована секция noinit
   /* Clear the zero segment */
   for ( pDest = & __bss_start; pDest < & __bss_end; )
   {
       * pDest ++ = 0;
   }

   /* Branch to main function */
   main();

   /* Infinite loop */
for (;;)
	;
}

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Или эти регистры в gcc 4.7.2 в случае их использования в вычислениях сохраняются автоматически.

Сейчас при невнимательном тестировании на первый взгляд всё работает и без __attribute__((__interrupt__)).

Не понял, причём тут gcc? Это аппаратно делается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не понял, причём тут gcc? Это аппаратно делается.

 

Не все регистры сохраняются. А с остальными (R4..R11) как быть - как обеспечить их сохранение? Или этого нет необходимости делать (они сохраняются при использовании?) В gcc.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не все регистры сохраняются. А с остальными (R4..R11) как быть - как обеспечить их сохранение? В gcc.

Их сохранение должна обеспечить сама вызываемая процедура. То есть - если процедуре надо использовать какой-либо из регистров R4-R11, то она его сама предварительно сохраняет, пользует и потом восстанавливает. Регистры R0-R3 процедура может использовать на свое усмотрение, их сохранять от процедуры не требуется.

Итого - произошло прерывание/исключение - флаги, R0-R3 и прочие сохранились, а остальные регистры R4-R11 вызванная процедура сама не разрушит.

Кстати, это не только к GCC относится, но и ко всем компиляторам, которые следуют APCS - "Procedure Call Standard for the ARM® Architecture" - документ есть на сайте ARM.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не все регистры сохраняются.

Конечно не все...

 

А с остальными (R4..R11) как быть - как обеспечить их сохранение?

Вас Си интересует?

Никак не обепечивать. Компилятор знает что делает...

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Из книжки J. Yiu

In many cases, the interrupt handler requires more than R0–R3 and R12 to process the interrupt, so we

might need to save some other registers as well. For C language users, there is no need to worry about this,

as the C function saves additional registers automatically if required. For assembly language users, their

interrupt handlers have to perform stack PUSH and POP to ensure the values of R4–R11 are preserved.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, значит функции обработчиков перерывания вообще ни в каких особых атрибутах в Cortex не нуждаются...

 

Из книжки J. Yiu

Хотелось прочитать это где-то в документации на компилятор. Например в главе calling conventions или ещё где-то в подобном месте. Для gcc 4.7.2 не нашёл.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

значит функции обработчиков перерывания вообще ни в каких особых атрибутах в Cortex не нуждаются...
Абсолютно верное заключение.

Но для того чтобы отличить обычную функцию от обработчика я всё равно предваряю её ключевым для кейла словом __irq.

Лишнего самодокументирования не бывает ИМХО.

void __irq EXTI9_5_IRQHandler(void)
{
    EXTI->PR = (1<<9); //сбросили флаг прерывания

    // do something else
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня

#ifdef __cplusplus
#  define INTERRUPT extern "C"
#else
#  define INTERRUPT
#endif

// ...

INTERRUPT void UART3_IRQHandler()
{
    // ...
}

 

Хотелось прочитать это где-то в документации на компилятор. Например в главе calling conventions или ещё где-то в подобном месте. Для gcc 4.7.2 не нашёл.

Уже ж сказано, что это стандартизовано ARM-ом и ссылка на документ дана:

Кстати, это не только к GCC относится, но и ко всем компиляторам, которые следуют APCS - "Procedure Call Standard for the ARM® Architecture" - документ есть на сайте ARM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пока мне APCS встретилось только в таком контексте:

-mapcs-frame

Generate a stack frame that is compliant with the ARM Procedure Call Standard for all functions, even if this is not strictly necessary for correct execution of the code. Specifying -fomit-frame-pointer with this option causes the stack frames not to be generated for leaf functions. The default is -mno-apcs-frame.

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

Просто меня спрашивают: вот ты сделал такой обработчик - а где гарантия, что регистры не используются? И я кроме честного слова за free software пока ничего не могу ответить...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Просто меня спрашивают: вот ты сделал такой обработчик - а где гарантия, что регистры не используются? И я кроме честного слова за free software пока ничего не могу ответить...

Как же, а в ассемблерный листинг посмотреть? Там все регистры видны. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот помню в Borland-овской документации было написано, в каких регистрах что возвращается (тогда ещё не

...

кроме честного слова за free software пока ничего не могу ответить...

GCC следует стандартным соглашениям для архитектуры ARM, поэтому документацию надо смотреть на архитектуру. Упомянутый документ, раздел 5 "THE BASE PROCEDURE CALL STANDARD", там все подробно расписано - и про основные регистры, и про регистры FPU и про флаги.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

GCC следует стандартным соглашениям для архитектуры ARM

Просто, где это сказано? Где написано, что эти соглашения действуют для gcc с ключами "по умолчанию".

Поиск чертырех букв APCS - абревиатуры названия на сайте gnu ничего не даёт (только как часть имени ключа).

Я так понимаю, KEIL следует стандарту своей же фирмы. Но кто декларировал совместимость keil и gcc? Как я знаю, это разные продукты...

Как же, а в ассемблерный листинг посмотреть? Там все регистры видны

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

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Красота! В качестве гарантии подсунуть листинг тому, кто спрашивает.

В качестве абсолютной гарантии продемонстрировать навороченный обработчик прерывания, чтобы всех имеющихся регистров не хватило.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В качестве абсолютной гарантии продемонстрировать навороченный обработчик прерывания, чтобы всех имеющихся регистров не хватило.

Ага, как тут его заставить... вот есть стейт-машина, вида void *state_mashine(void *pc) и вызывается из нескольких прерываний, вроде бы действий внутри - мама не горюй. А все равно обходится преимущественно r0-r3, сохраняет r7,lr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...