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

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

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

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

 

 

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

 

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

 

 

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

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


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

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

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. ...

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


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

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? :)

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


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

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

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

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

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

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

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

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


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

Попробуйте взять мою сборку 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.

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


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

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

 

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

 

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

 

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

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


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

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

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

 

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

 

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

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


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

Случайно наткнулся: 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")))

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

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


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

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

 

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

SKIP

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

 

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

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

 

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

 

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

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


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

Вкраце, советуют описать обработчик 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 */

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


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

Убил субботу, ночь и полсегодня в поисках кривизны. Нашел откуда рога растут - функция разворачивания пролога в /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 в аборте или нет? Как считает?

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

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


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

...

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 тумб я тоже не пользую.

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


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

Ну че? потестируете?

 

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

 

Может для 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)

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


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

я еще не выложил. завтра постатаюсь с утра закачать.

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


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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...