реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Closed TopicStart new topic
> Соглашения по регистрам, Cortex M3, gcc 4.7.2
Genadi Zawidowsk...
сообщение Feb 12 2013, 18:55
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Вижу, что в документе 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 никаких изменений режима работы процессора не делается.
CODE
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 - Feb 12 2013, 19:18
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 12 2013, 19:10
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Genadi Zawidowski @ Feb 12 2013, 20:55) *
Или эти регистры в gcc 4.7.2 в случае их использования в вычислениях сохраняются автоматически.
Сейчас при невнимательном тестировании на первый взгляд всё работает и без __attribute__((__interrupt__)).

Не понял, причём тут gcc? Это аппаратно делается.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 12 2013, 19:19
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Цитата(_Артём_ @ Feb 12 2013, 23:10) *
Не понял, причём тут gcc? Это аппаратно делается.


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

Сообщение отредактировал Genadi Zawidowski - Feb 12 2013, 19:27
Go to the top of the page
 
+Quote Post
VslavX
сообщение Feb 12 2013, 19:29
Сообщение #4


embarrassed systems engineer
*****

Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038



Цитата(Genadi Zawidowski @ Feb 12 2013, 21:19) *
Не все регистры сохраняются. А с остальными (R4..R11) как быть - как обеспечить их сохранение? В gcc.

Их сохранение должна обеспечить сама вызываемая процедура. То есть - если процедуре надо использовать какой-либо из регистров R4-R11, то она его сама предварительно сохраняет, пользует и потом восстанавливает. Регистры R0-R3 процедура может использовать на свое усмотрение, их сохранять от процедуры не требуется.
Итого - произошло прерывание/исключение - флаги, R0-R3 и прочие сохранились, а остальные регистры R4-R11 вызванная процедура сама не разрушит.
Кстати, это не только к GCC относится, но и ко всем компиляторам, которые следуют APCS - "Procedure Call Standard for the ARM® Architecture" - документ есть на сайте ARM.

Go to the top of the page
 
+Quote Post
_Артём_
сообщение Feb 12 2013, 19:33
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Genadi Zawidowski @ Feb 12 2013, 21:19) *
Не все регистры сохраняются.

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

Цитата(Genadi Zawidowski @ Feb 12 2013, 21:19) *
А с остальными (R4..R11) как быть - как обеспечить их сохранение?

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

Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 12 2013, 19:33
Сообщение #6


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Из книжки 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.
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 12 2013, 19:36
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



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

Цитата(ViKo @ Feb 12 2013, 23:33) *
Из книжки J. Yiu

Хотелось прочитать это где-то в документации на компилятор. Например в главе calling conventions или ещё где-то в подобном месте. Для gcc 4.7.2 не нашёл.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 13 2013, 05:38
Сообщение #8


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Genadi Zawidowski @ Feb 12 2013, 23:36) *
значит функции обработчиков перерывания вообще ни в каких особых атрибутах в Cortex не нуждаются...
Абсолютно верное заключение.
Но для того чтобы отличить обычную функцию от обработчика я всё равно предваряю её ключевым для кейла словом __irq.
Лишнего самодокументирования не бывает ИМХО.
Код
void __irq EXTI9_5_IRQHandler(void)
{
    EXTI->PR = (1<<9); //сбросили флаг прерывания

    // do something else
}


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 13 2013, 06:57
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



У меня
Код
#ifdef __cplusplus
#  define INTERRUPT extern "C"
#else
#  define INTERRUPT
#endif

// ...

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


Цитата(Genadi Zawidowski @ Feb 12 2013, 21:36) *
Хотелось прочитать это где-то в документации на компилятор. Например в главе calling conventions или ещё где-то в подобном месте. Для gcc 4.7.2 не нашёл.

Уже ж сказано, что это стандартизовано ARM-ом и ссылка на документ дана:
Цитата(VslavX @ Feb 12 2013, 21:29) *
Кстати, это не только к GCC относится, но и ко всем компиляторам, которые следуют APCS - "Procedure Call Standard for the ARM® Architecture" - документ есть на сайте ARM.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 13 2013, 18:49
Сообщение #10


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Пока мне 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 пока ничего не могу ответить...
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 14 2013, 03:59
Сообщение #11


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Genadi Zawidowski @ Feb 13 2013, 21:49) *
Просто меня спрашивают: вот ты сделал такой обработчик - а где гарантия, что регистры не используются? И я кроме честного слова за free software пока ничего не могу ответить...

Как же, а в ассемблерный листинг посмотреть? Там все регистры видны. sm.gif
Go to the top of the page
 
+Quote Post
VslavX
сообщение Feb 14 2013, 06:19
Сообщение #12


embarrassed systems engineer
*****

Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038



Цитата(Genadi Zawidowski @ Feb 13 2013, 20:49) *
Вот помню в Borland-овской документации было написано, в каких регистрах что возвращается (тогда ещё не
...
кроме честного слова за free software пока ничего не могу ответить...

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

Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Feb 14 2013, 09:31
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



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

Просто, где это сказано? Где написано, что эти соглашения действуют для gcc с ключами "по умолчанию".
Поиск чертырех букв APCS - абревиатуры названия на сайте gnu ничего не даёт (только как часть имени ключа).
Я так понимаю, KEIL следует стандарту своей же фирмы. Но кто декларировал совместимость keil и gcc? Как я знаю, это разные продукты...
Цитата
Как же, а в ассемблерный листинг посмотреть? Там все регистры видны

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

Сообщение отредактировал Genadi Zawidowski - Feb 14 2013, 09:37
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 14 2013, 10:37
Сообщение #14


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(Genadi Zawidowski @ Feb 14 2013, 12:31) *
Ассемблерный листинг зависит от кода... от сложности выражений. Простые функции ничего не используют, только LR.

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

В принципе, любой компилятор C для любого процессора должен при входе в функцию сохранить в стеке те регистры, которые используются в этой функции. Или переключиться на другой набор регистров.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 14 2013, 10:53
Сообщение #15


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(ViKo @ Feb 14 2013, 14:37) *
В качестве абсолютной гарантии продемонстрировать навороченный обработчик прерывания, чтобы всех имеющихся регистров не хватило.

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

2 страниц V   1 2 >
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 6th July 2025 - 21:38
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016