Jump to content

    
Sign in to follow this  
Alex03

GCC и прерывания в C коде

Recommended Posts

Вчера понадобилать Release версия проекта, скомпилил, ни в какую работать не захотела, глючило всё как могло.

Пол дня убил пока не понял что наступил на известные грабли GCC, неправильное генерение пролога/эпилога для прерываний. Описанные тут и тут

 

 

Всё это под CW 1.6 b 3. там GCC 4.1.0.

 

Притом на сайте Rowley Associates примерно тут (сейчас чтото недоступен) говорится что с уровнем оптимизации 1 ( -O1 ) всё ОК! Но как я понял это в предыдущих версиях (3.х.х) оно работало, а сейчас нет.

 

 

Вооот. Качать кучу исходников и патчить их чтото не хочется, мож кто уже проделал сию работу?

Share this post


Link to post
Share on other sites
Вооот. Качать кучу исходников и патчить их чтото не хочется, мож кто уже проделал сию работу?

PR16634: Wrong-code for IRQ functions. - http://gcc.gnu.org/ml/gcc-patches/2006-08/msg00230.html

When generating interworked armv4t code gcc generates incorrect function

epilogue code for IRQ/FIQ functions. ...

Share this post


Link to post
Share on other sites
PR16634: Wrong-code for IRQ functions. - http://gcc.gnu.org/ml/gcc-patches/2006-08/msg00230.html

When generating interworked armv4t code gcc generates incorrect function

epilogue code for IRQ/FIQ functions. ...

 

Так я практически тудаже ссылку дал. Т.е. в конце страницы которую я обозвал как второй "тут" (т.е. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16634) эта ссылка есть. И я понятно там был.

Мне не хочется качать исходники GCC, патчить, компилять.

 

Кстати вопрос к знающим, а сам GCC под ARM компилять надо обязательно GCC-x86 (а то и со всякими бинутилами и т.д.)?

Или можно и в MS VC 2003? :)

Share this post


Link to post
Share on other sites
Кстати вопрос к знающим, а сам GCC под ARM компилять надо обязательно GCC-x86 (а то и со всякими бинутилами и т.д.)?

Или можно и в MS VC 2003? :)

Попробуйте взять мою сборку 4.1.2 http://www.klen.org/Projects/Embeded-gnu-t...last_build.html

В нем arm.c изменен в части касающей строк которык в патче указаны.

Если будете пробывать напишите че вышло. будем разбиратся.

Edited by klen

Share this post


Link to post
Share on other sites
Попробуйте взять мою сборку 4.1.2 http://www.klen.org/Projects/Embeded-gnu-t...last_build.html

В нем arm.c изменен в части касающей строк которык в патче указаны.

Если будете пробывать напишите че вышло. будем разбиратся.

 

Спасибо, но не прокатило.

 

С код

 

void testISR(void) __attribute__ ((interrupt ("IRQ")));
void testISR(void)
{
    testIsrFn();
}

 

Код который генерился ранее, т.е. GCC 4.1.0 с оптимизацией Level 1

       E24EE004   sub lr, lr, #0x00000004
       E92D500F   stmfd sp!, {r0-r3, r12, lr}
       EBFFFFFE   bl 0x000000a4                       // testIsrFn()
       E8BD500F   ldmfd sp!, {r0-r3, r12, lr}
       E25EF004   subs pc, lr, #0x00000004

 

Код который генерится с GCC 4.1.2 с оптимизацией Level 1

       E24EE004   sub lr, lr, #0x00000004
       E92D500F   stmfd sp!, {r0-r3, r12, lr}
       EBFFFFFE   bl 0x000000b0                       // testIsrFn()
       E8BD500F   ldmfd sp!, {r0-r3, r12, lr}
       E25EF004   subs pc, lr, #0x00000004
}

Т.е. тоже самое, там проблема что 4 из lr дважды вычитается.

 

 

Рабочий код который генерится с обоими GCC без оптимизации (дебаг)

       E52DC004   str r12, [sp, #-0x004]!
       E1A0C00D   mov r12, sp
       E92DD80F   stmfd sp!, {r0-r3, r11-r12, lr-pc}
       E24CB004   sub r11, r12, #0x00000004
       EBFFFFFE   bl 0x00000010                       // testIsrFn()
       E24BD01C   sub sp, r11, #0x0000001c
       E89D680F   ldmfd sp, {r0-r3, r11, sp-lr}
       E8BD1000   ldmfd sp!, {r12}
       E25EF004   subs pc, lr, #0x00000004

С ключиком -mapcs-frame код генерится как в дебаге.

 

 

Ну и на вот это не ответишь?

Кстати вопрос к знающим, а сам GCC под ARM компилять надо обязательно GCC-x86 (а то и со всякими бинутилами и т.д.)?

Или можно и в MS VC 2003? :)

 

И ещё klen почему твои бинарники раза в 3 больше чем которые с crossworks-ом? Мож их стрипом?

 

Кстати статус у патча нифига не CLOSED.

Share this post


Link to post
Share on other sites

По поводу глюка - я правильно понял что он проявляется при отличном от -O0 ключе оптимизации?

 

Бинарники у меня большие потому что я их так собираю чтоб на любой машинке работали и не требовали никаких библиотек - все статически влинковывается.

 

Скомпилить часть исходников gcc может получится, другая часть не скомпилируется потому что есть gcc расширения и особенности синтаксиса С языка которые VC++ не пропустит. А вот собрать без binutils не получится и вовсе, как я думаю.

 

А зачем gcc собирать с помощю не gcc??? какой от этого кайф?

Share this post


Link to post
Share on other sites
По поводу глюка - я правильно понял что он проявляется при отличном от -O0 ключе оптимизации?

Правильно. По крайней мере при -O1, -O2 точно.

 

А зачем gcc собирать с помощю не gcc??? какой от этого кайф?

 

затем что нет его у меня пока! :) Тока в линухе.

Share this post


Link to post
Share on other sites

Случайно наткнулся: http://www.armkits.com/support/FAQanswer.asp?id=142

 

Вкраце, советуют описать обработчик irq на асме:

irq_entry:  .EXTERN irq_func
.GLOBAL irq_entry
stmdb sp!, {r0-r11, ip, lr} /* Save r0-r11, ip, lr */
ldr r0, = irq_func
mov lr, pc
bx r0           /* Use C interruption program*/
ldmia sp!, {r0-r11, ip, lr}        /* Resume r0, ip, lr */
subs pc, r14, #4         /* Interruption and return */

 

из которого и будет вызываться вызывать функция обработки прерывания, описанная на C, но безо всяких __attribute__ ((interrupt ("IRQ")))

Edited by yaghtn

Share this post


Link to post
Share on other sites
Случайно наткнулся: http://www.armkits.com/support/FAQanswer.asp?id=142

 

Вкраце, советуют описать обработчик irq на асме:

SKIP

из которого и будет вызываться вызывать функция обработки прерывания, описанная на C, но безо всяких __attribute__ ((interrupt ("IRQ")))

 

Эт всё понятно, можно и naked функцию объявить со своими прологом/эпилогом в виде асм-вставки.

Просто обидно что глюку 2 года а править его никто не думает. :)

 

Кстати в приведённом примере сохраняются все r0-r11 и вызывается функция, которая в свою очередь опять будет сохранять часть из этих регистров если их пользует. Т.е. оверхед по времени и стеку в прерывании.

 

Но в любом случае спасибо! :)

Share this post


Link to post
Share on other sites
Вкраце, советуют описать обработчик irq на асме:

irq_entry:  .EXTERN irq_func
.GLOBAL irq_entry
stmdb sp!, {r0-r11, ip, lr} /* Save r0-r11, ip, lr */
ldr r0, = irq_func
mov lr, pc
bx r0           /* Use C interruption program*/
ldmia sp!, {r0-r11, ip, lr}        /* Resume r0, ip, lr */
subs pc, r14, #4         /* Interruption and return */

 

тогда уж так лучше, короче на 2 команды

irq_entry:  .EXTERN irq_entry
.GLOBAL irq_entry
stmdb sp!, {r0-r11, ip, lr} /* Save r0-r11, ip, lr */
bl irq_entry           /* Use C interruption program*/
ldmia sp!, {r0-r11, ip, lr}        /* Resume r0, ip, lr */
subs pc, r14, #4         /* Interruption and return */

Share this post


Link to post
Share on other sites

Убил субботу, ночь и полсегодня в поисках кривизны. Нашел откуда рога растут - функция разворачивания пролога в /gcc/config/arm/arm.c:arm_expand_prologue, поправил, пересобрал, эпилог начал генерится правильно(???) c оптимизацией О1,O2,О3,Оs. компиллер gcc 4.1.2-20060930. Вот результат:

 

-О0 (без оптимизации)

void uartISR(void)__attribute__ (( interrupt("IRQ")));
void uartISR(void)
{
       E52DC004   str r12, [sp, #-0x004]!
       E1A0C00D   mov r12, sp
       E92DD80F   stmfd sp!, {r0-r3, r11-r12, lr-pc}
       E24CB004   sub r11, r12, #0x00000004
       E24DD008   sub sp, sp, #0x00000008

//-----целевой код прерывания(конец пролога)-----------
  portBASE_TYPE Tmp = U0IIR;
       E3A03903   mov r3, #0x01800000
       E283328E   add r3, r3, #0x80000023
       E5D33000   ldrb r3, [r3]
............................................  
VICVectAddr = 0;
       E3A03000   mov r3, #0x00000000
       E2433EFD   sub r3, r3, #0x03f40000
       E3A02000   mov r2, #0x00000000
       E5832000   str r2, [r3]
}
//-----целевой код прерывания(начало эпилога)-----------
       E24BD01C   sub sp, r11, #0x0000001c
       E89D680F   ldmfd sp, {r0-r3, r11, sp-lr}
       E8BD1000   ldmfd sp!, {r12}
       E25EF004   subs pc, lr, #0x00000004

оптимизация -О1...Оs

void uartISR(void)__attribute__ (( interrupt("IRQ")));
void uartISR(void)
{
{
       E92D500F   stmfd sp!, {r0-r3, r12, lr}
//-----целевой код прерывания(конец пролога)-----------
  portBASE_TYPE Tmp = U0IIR;
       E3A0320E   mov r3, #0x80000003
       E2832903   add r2, r3, #0x01800000
       E5D23008   ldrb r3, [r2, #+0x008]
.....................................
VICVectAddr = 0;
       E3A02000   mov r2, #0x00000000
       E3E03000   mvn r3, #0x00000000
       E5032FCF   str r2, [r3, #-0xfcf]
}
//-----целевой код прерывания(начало эпилога)-----------
       E8BD500F   ldmfd sp!, {r0-r3, r12, lr}
       E25EF004   subs pc, lr, #0x00000004

В последнем листе приведен для -O1, поскольку при других оптимизациях компиллеров изменялся только целевой код, то приведен только один лист - эпилог и пролог при всех отличгых от -O0 одинаковы.

 

Завтра или сегодня выложу поправленую сборку (дома интернет сдох, пишу через мобильник). Непроверял при заходе в irq/fiq из THUMB и выходе внего. Прошу проверить. Нужно вобще потестировать.

Лично у меня проект завелся на всех оптимизациях(раньше ессесенго все работало только без оптимизации). Проект состоящий из 4задач FreeRTOS + 20кб всякого разношерстного кода работы с переферией. Работает не жужит. Дмаю что еслиб где былаб ошибочка то хрен работалоб - куча стеков, heap, и тд - все динамически дышит - и не падает уже минут 40. микросхемка lpc2103 Но! я ваще тумб не пользую - нада проверять.

 

Еще вопрос. При выходе из irq/frq возврат на прерванную команду - subs pc, lr, #0x00000004. А вот при DAbort всетаки на две команды нада отматывать(по моему разумению изза того что это исключение в v4t происходить через одну команду если возникла ошибка озу). Посему нада в пепилоге subs pc, lr, #0x00000008 применять. Сейчас для всех исключений кроме SWI все едино. Делать -8 в аборте или нет? Как считает?

Edited by klen

Share this post


Link to post
Share on other sites
...

SKIP

...

 

Завтра или сегодня выложу поправленую сборку (дома интернет сдох, пишу через мобильник). Непроверял при заходе в irq/fiq из THUMB и выходе внего. Прошу проверить. Нужно вобще потестировать.

Лично у меня проект завелся на всех оптимизациях(раньше ессесенго все работало только без оптимизации). Проект состоящий из 4задач FreeRTOS + 20кб всякого разношерстного кода работы с переферией. Работает не жужит. Дмаю что еслиб где былаб ошибочка то хрен работалоб - куча стеков, heap, и тд - все динамически дышит - и не падает уже минут 40. микросхемка lpc2103 Но! я ваще тумб не пользую - нада проверять.

 

Еще вопрос. При выходе из irq/frq возврат на прерванную команду - subs pc, lr, #0x00000004. А вот при DAbort всетаки на две команды нада отматывать(по моему разумению изза того что это исключение в v4t происходить через одну команду если возникла ошибка озу). Посему нада в пепилоге subs pc, lr, #0x00000008 применять. Сейчас для всех исключений кроме SWI все едино. Делать -8 в аборте или нет? Как считает?

 

По моему и сейчас не едино, и надо не едино.

В частности для FIQ не сохраняется R12, ибо он там свой теневой.

Кстати для пустых обработчиков код для IRQ генерится правильно и состоит из одной команды:

       E25EF004   subs pc, lr, #0x00000004

 

И даже не только для пустых но и для таких:

 

void testIsrFn()
{
}
void testISR_IRQ(void) __attribute__ ((interrupt ("IRQ")));
void testISR_IRQ(void)
{
    testIsrFn();
}

Оптимизация блин! :)

 

Про DAbort и т.д. не скажу т.к. абсолютно не силён в ARM асме и соответственно архитектуре.

Но ИМХО возвращаться из abort-ов в проциках без MMU както не провильно. Т.е. если есть ОС то она должна снять/перезапустить задачу. Если без ОС то итого хуже.

Я у себя в железке матерюсь на индикатор и стопарюсь в пустом цикле, ибо этого не должнобыть никогда!

Для проциков с ММУ, кэшами и т.д. видимо есть другие пути решения, но я с ними не работал.

 

PS тумб я тоже не пользую.

Share this post


Link to post
Share on other sites
Ну че? потестируете?

 

Если там же, то там нет?

 

Может для CW и опции взять соответствующие?

Из вот этого?

Using built-in specs.
Target: arm-unknown-elf
Configured with: ../gcc-2006q1/configure --target=arm-unknown-elf --build=i686-pc-mingw32 --host=i686-pc-mingw32 --prefix=/c/gcc-build/install : (reconfigured) ../gcc-2006q1/configure --target=arm-unknown-elf --build=i686-pc-mingw32 --host=i686-pc-mingw32 --prefix=/c/gcc-build/install
Thread model: single
gcc version 4.1.0 (CodeSourcery ARM)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this