GenaSPB 11 12 февраля, 2013 Опубликовано 12 февраля, 2013 (изменено) · Жалоба Вижу, что в документе 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 (;;) ; } Изменено 12 февраля, 2013 пользователем Genadi Zawidowski Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 12 февраля, 2013 Опубликовано 12 февраля, 2013 · Жалоба Или эти регистры в gcc 4.7.2 в случае их использования в вычислениях сохраняются автоматически. Сейчас при невнимательном тестировании на первый взгляд всё работает и без __attribute__((__interrupt__)). Не понял, причём тут gcc? Это аппаратно делается. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 12 февраля, 2013 Опубликовано 12 февраля, 2013 (изменено) · Жалоба Не понял, причём тут gcc? Это аппаратно делается. Не все регистры сохраняются. А с остальными (R4..R11) как быть - как обеспечить их сохранение? Или этого нет необходимости делать (они сохраняются при использовании?) В gcc. Изменено 12 февраля, 2013 пользователем Genadi Zawidowski Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 12 февраля, 2013 Опубликовано 12 февраля, 2013 · Жалоба Не все регистры сохраняются. А с остальными (R4..R11) как быть - как обеспечить их сохранение? В gcc. Их сохранение должна обеспечить сама вызываемая процедура. То есть - если процедуре надо использовать какой-либо из регистров R4-R11, то она его сама предварительно сохраняет, пользует и потом восстанавливает. Регистры R0-R3 процедура может использовать на свое усмотрение, их сохранять от процедуры не требуется. Итого - произошло прерывание/исключение - флаги, R0-R3 и прочие сохранились, а остальные регистры R4-R11 вызванная процедура сама не разрушит. Кстати, это не только к GCC относится, но и ко всем компиляторам, которые следуют APCS - "Procedure Call Standard for the ARM® Architecture" - документ есть на сайте ARM. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 12 февраля, 2013 Опубликовано 12 февраля, 2013 · Жалоба Не все регистры сохраняются. Конечно не все... А с остальными (R4..R11) как быть - как обеспечить их сохранение? Вас Си интересует? Никак не обепечивать. Компилятор знает что делает... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 февраля, 2013 Опубликовано 12 февраля, 2013 · Жалоба Из книжки 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. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 12 февраля, 2013 Опубликовано 12 февраля, 2013 · Жалоба Спасибо, значит функции обработчиков перерывания вообще ни в каких особых атрибутах в Cortex не нуждаются... Из книжки J. Yiu Хотелось прочитать это где-то в документации на компилятор. Например в главе calling conventions или ещё где-то в подобном месте. Для gcc 4.7.2 не нашёл. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 13 февраля, 2013 Опубликовано 13 февраля, 2013 · Жалоба значит функции обработчиков перерывания вообще ни в каких особых атрибутах в Cortex не нуждаются...Абсолютно верное заключение. Но для того чтобы отличить обычную функцию от обработчика я всё равно предваряю её ключевым для кейла словом __irq. Лишнего самодокументирования не бывает ИМХО. void __irq EXTI9_5_IRQHandler(void) { EXTI->PR = (1<<9); //сбросили флаг прерывания // do something else } Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 13 февраля, 2013 Опубликовано 13 февраля, 2013 · Жалоба У меня #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. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 13 февраля, 2013 Опубликовано 13 февраля, 2013 · Жалоба Пока мне 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 пока ничего не могу ответить... Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 14 февраля, 2013 Опубликовано 14 февраля, 2013 · Жалоба Просто меня спрашивают: вот ты сделал такой обработчик - а где гарантия, что регистры не используются? И я кроме честного слова за free software пока ничего не могу ответить... Как же, а в ассемблерный листинг посмотреть? Там все регистры видны. :) Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 14 февраля, 2013 Опубликовано 14 февраля, 2013 · Жалоба Вот помню в Borland-овской документации было написано, в каких регистрах что возвращается (тогда ещё не ... кроме честного слова за free software пока ничего не могу ответить... GCC следует стандартным соглашениям для архитектуры ARM, поэтому документацию надо смотреть на архитектуру. Упомянутый документ, раздел 5 "THE BASE PROCEDURE CALL STANDARD", там все подробно расписано - и про основные регистры, и про регистры FPU и про флаги. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 14 февраля, 2013 Опубликовано 14 февраля, 2013 (изменено) · Жалоба GCC следует стандартным соглашениям для архитектуры ARM Просто, где это сказано? Где написано, что эти соглашения действуют для gcc с ключами "по умолчанию". Поиск чертырех букв APCS - абревиатуры названия на сайте gnu ничего не даёт (только как часть имени ключа). Я так понимаю, KEIL следует стандарту своей же фирмы. Но кто декларировал совместимость keil и gcc? Как я знаю, это разные продукты... Как же, а в ассемблерный листинг посмотреть? Там все регистры видны Ассемблерный листинг зависит от кода... от сложности выражений. Простые функции ничего не используют, только LR. Изменено 14 февраля, 2013 пользователем Genadi Zawidowski Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 14 февраля, 2013 Опубликовано 14 февраля, 2013 · Жалоба Ассемблерный листинг зависит от кода... от сложности выражений. Простые функции ничего не используют, только LR. Красота! В качестве гарантии подсунуть листинг тому, кто спрашивает. В качестве абсолютной гарантии продемонстрировать навороченный обработчик прерывания, чтобы всех имеющихся регистров не хватило. В принципе, любой компилятор C для любого процессора должен при входе в функцию сохранить в стеке те регистры, которые используются в этой функции. Или переключиться на другой набор регистров. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 14 февраля, 2013 Опубликовано 14 февраля, 2013 · Жалоба В качестве абсолютной гарантии продемонстрировать навороченный обработчик прерывания, чтобы всех имеющихся регистров не хватило. Ага, как тут его заставить... вот есть стейт-машина, вида void *state_mashine(void *pc) и вызывается из нескольких прерываний, вроде бы действий внутри - мама не горюй. А все равно обходится преимущественно r0-r3, сохраняет r7,lr Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться