Пропуски зажигания при сборке GCC и новыми верс. IAR

Обсуждение прошивок SECU-3. Discussion of SECU-3 firmware.

Moderator: STC

Qwertty
LQFP144 - On Top Of The Game
Posts: 252
Joined: Thu Jul 26, 2012 12:35 pm

Re: Пропуски зажигания при сборке GCC и новыми верс. IAR

Post by Qwertty »

Хорошо, так понять сложно. На примерах попробую.
И так тестовый пример очень простой:

Code: Select all

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

static void test_func(void)
{
    PORTD |= (1<<PD5);
}

ISR(TIMER0_OVF_vect)
{
    test_func();
}

int main(void)
{
while(1)
    {
    };
}
Листинг прерывания:

Code: Select all

---- test_isr.c -----------------------------------------------------------------------------------
12:       {
+00000049:   921F        PUSH    R1               Push register on stack
+0000004A:   920F        PUSH    R0               Push register on stack
+0000004B:   B60F        IN      R0,0x3F          In from I/O location
+0000004C:   920F        PUSH    R0               Push register on stack
+0000004D:   2411        CLR     R1               Clear Register
7:            PORTD |= (1<<PD5);
+0000004E:   9A95        SBI     0x12,5           Set bit in I/O register
+0000004F:   900F        POP     R0               Pop register from stack
+00000050:   BE0F        OUT     0x3F,R0          Out to I/O location
+00000051:   900F        POP     R0               Pop register from stack
+00000052:   901F        POP     R1               Pop register from stack
+00000053:   9518        RETI                     Interrupt return
Вот тут видно стандартный оверхед ГЦЦ на простых обработчиках. Этот компилятор всегда сохраняет SREG. Ну и заодно ZERO регистр. Но это сейчас неважно.
Сама функция просто проинлайнена что очень логично. Изменим пример на работу с указателем:

Code: Select all

#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

typedef void (*FuncPtr)(void);
FuncPtr FPtr;

static void test_func(void)
{
    PORTD |= (1<<PD5);
}

ISR(TIMER0_OVF_vect)
{
    (FPtr)();
}
Листинг обработчика прерывания стал таким:

Code: Select all

@0000004B: __vector_11
17:       {
+0000004B:   921F        PUSH    R1               Push register on stack
+0000004C:   920F        PUSH    R0               Push register on stack
+0000004D:   B60F        IN      R0,0x3F          In from I/O location
+0000004E:   920F        PUSH    R0               Push register on stack
+0000004F:   2411        CLR     R1               Clear Register
+00000050:   932F        PUSH    R18              Push register on stack
+00000051:   933F        PUSH    R19              Push register on stack
+00000052:   934F        PUSH    R20              Push register on stack
+00000053:   935F        PUSH    R21              Push register on stack
+00000054:   936F        PUSH    R22              Push register on stack
+00000055:   937F        PUSH    R23              Push register on stack
+00000056:   938F        PUSH    R24              Push register on stack
+00000057:   939F        PUSH    R25              Push register on stack
+00000058:   93AF        PUSH    R26              Push register on stack
+00000059:   93BF        PUSH    R27              Push register on stack
+0000005A:   93EF        PUSH    R30              Push register on stack
+0000005B:   93FF        PUSH    R31              Push register on stack
18:           (FPtr)();
+0000005C:   91E00060    LDS     R30,0x0060       Load direct from data space
+0000005E:   91F00061    LDS     R31,0x0061       Load direct from data space
+00000060:   9509        ICALL                    Indirect call to (Z)
+00000061:   91FF        POP     R31              Pop register from stack
+00000062:   91EF        POP     R30              Pop register from stack
+00000063:   91BF        POP     R27              Pop register from stack
+00000064:   91AF        POP     R26              Pop register from stack
+00000065:   919F        POP     R25              Pop register from stack
+00000066:   918F        POP     R24              Pop register from stack
+00000067:   917F        POP     R23              Pop register from stack
+00000068:   916F        POP     R22              Pop register from stack
+00000069:   915F        POP     R21              Pop register from stack
+0000006A:   914F        POP     R20              Pop register from stack
+0000006B:   913F        POP     R19              Pop register from stack
+0000006C:   912F        POP     R18              Pop register from stack
+0000006D:   900F        POP     R0               Pop register from stack
+0000006E:   BE0F        OUT     0x3F,R0          Out to I/O location
+0000006F:   900F        POP     R0               Pop register from stack
+00000070:   901F        POP     R1               Pop register from stack
+00000071:   9518        RETI    
Разница думаю заметна.
При этом сама функция вообще регистров не использует:

Code: Select all

+00000049:   9A95        SBI     0x12,5           Set bit in I/O register
+0000004A:   9508        RET                      Subroutine return
Тот же эффект будет если сделать вызов обычным, без указателя, но перенести void test_func(void) в другой файл. Т.е. не в тот где обработчик.
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Пропуски зажигания при сборке GCC и новыми верс. IAR

Post by STC »

Qwertty спасибо за пример!
В моем обработчике прерывания такие функции (что по указателю, что без него) особой погоды не сделают, так как там и без них все плохо :lol: Там одно только деление 32/16 все перекрывает :lol:
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
Qwertty
LQFP144 - On Top Of The Game
Posts: 252
Joined: Thu Jul 26, 2012 12:35 pm

Re: Пропуски зажигания при сборке GCC и новыми верс. IAR

Post by Qwertty »

Выше потеря примерно ТРЕХ тактов вызвала панику и желание уйти от битовых полей на макросы. Это в принципе логично и без привязки к оптимальности кода. Тут же 24 такта лишних паники не вызывают. :) Плюс лишние такты на вызов и на считывание указателя. Вот так понемногу и набирается приличное количество лишних действий.
Кстати у варианта GCC помимо минуса от лишнего времени выполнения есть и плюс - независимость этого времени от параметра функции. Иногда это важней.
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Пропуски зажигания при сборке GCC и новыми верс. IAR

Post by STC »

Все, покончено с пропусками и на GCC. Теперь бы еще оптимизировать тяжеловесное прерывание и вообще было бы супер :-).
Обновил исходники и бинарники. Продолжаю охоту за багами.
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
User avatar
STC
LQFP144 - On Top Of The Game
Posts: 2420
Joined: Fri Oct 22, 2010 10:47 pm
Location: Ukraine, Kiev
Contact:

Re: Пропуски зажигания при сборке GCC и новыми верс. IAR

Post by STC »

Вопросы по сборке прошивки перенесены в отдельную тему в разделе "Поддержка пользователей" viewtopic.php?f=71&t=2028
Author of the SECU-3 project. SECU-3 Engine control unit / Ignition control system
SECU-3.org (Русский)
SECU-3.org (English)
SECU-3 Club ВКонтакте
SECU-3 EMS Project Facebook
Post Reply