Простой вызов функции увеличивает код на 150 байт

Тема в разделе "Arduino & Shields", создана пользователем dvanto, 26 дек 2019.

Метки:
  1. dvanto

    dvanto Нерд

    Беда...

    Написал программу управления насосом
    Стал прикручивать EEPROM - пишет, но как-то не понятно (читает мусор)
    Для отладки добавляю вызов функции read_flash();, которая читает EEPROM и пишет, что записалось

    Внезапно беда....
    Без вызова код помещается в Arduino Pro mega168 16mhz:
    с одним дополнительным вызовом вырастает на 150 байтов:
    Что не так?
    Как исправить?


    Код (C++):

    void PumpOff()
    {
      Log.notice( FF("Pump OFF - done: %i seconds" CR), pump_last_time );

      //noInterrupts();
      digitalWrite(SW_VALVE, LOW);
      digitalWrite(SW_MOTOR, LOW);
      //interrupts();

      pump = PUMP_OFF;

        lcd_on(true);
      lcd_status();

      // stat
       
      fv_pump.total_time += pump_last_time;
      fv_pump.total_volume += pump_last_volume;
        write_flash();

      // Log.notice( FF( "done: %i seconds" CR), pump_last_time );

       read_flash(); // <--- ПРОБЛЕМА ТУТ


      FlowTimeout.stop();
      TankTimeout.stop();

    }

    #define EEPROM_f(f, e_offset, v)        { EEPROM.f( e_offset, v ); e_offset += sizeof(v); }

    bool read_flash()
    {
        int e_offset = FLASH_OFFSET;
        uint16_t sign;

        EEPROM_f( get, e_offset, sign );
        e_offset += sizeof(sign);
        // Log.notice(STR_SXd_CR, FF("sign = "), sign, __LINE__);

        if ( sign == FLASH_SIGNATURE )
        {
            // Log.notice(STR_SXd_CR, FF(""), 0, __LINE__);
            EEPROM.get( e_offset, fv_pump );
            e_offset += sizeof(fv_pump);
            EEPROM.get( e_offset, fv_errors );
            EEPROM_f( get, e_offset, fv_pump.cnt );
            EEPROM_f( get, e_offset, fv_pump.owfl );
            EEPROM_f( get, e_offset, fv_pump.total_time );
            EEPROM_f( get, e_offset, fv_pump.total_volume );

            for(byte i=0; i<sizeof(fv_errors); i++ )
                EEPROM_f( get, e_offset, fv_errors[i] );
       
            // Log.notice(FF("read_flash done %d %d" CR), FLASH_OFFSET, e_offset);
       
            print_flash(__LINE__);
            return true;
        }
        else
        {
            Log.notice(STR_SXd_CR, FF(""), 0, __LINE__);
            for (byte i=0; i<sizeof(fv_errors); fv_errors[i++]=0);
            print_flash(__LINE__);
            write_flash(FLASH_SIGNATURE);
            return false;
        }

    }

     
    скетч приложил файлом - он большой
     

    Вложения:

    • wellpump.ino
      Размер файла:
      24,6 КБ
      Просмотров:
      140
  2. DIYMan

    DIYMan Guest

    Что предлагаю сходу:

    1. Отказаться от sprintf, переписав форматирование времени вручную - это не так сложно, код получится меньше;
    2. Везде, где употребляется
    Код (C++):
    for(byte i=0; i<sizeof(fv_errors); i++)
    во-первых, избавиться от compiler warning, заменив byte на size_t, во-вторых - избавиться от потенциального косяка при смене размерности одного элемента массива fv_errors, т.е. написать вот так:
    Код (C++):
    for(size_t i=0; i<sizeof(fv_errors)/sizeof(fv_errors[0]); i++)
    3. Отказаться от sprintf в других местах - избавитесь от ненужных буферов, размер бинарника уменьшится. Мне, например, неясен сакральный смысл вот этой конструкции:
    Код (C++):
    sprintf(buf, "%s%c%c%c %s %04u",
                        s,
                        c1 = sw(sw_Overflow.pressed(), 'O'),
                        c2 = sw(sw_HighMark.pressed(), 'F'),
                        c3 = sw( sw_LowMark.pressed(), 'E'),
                        sprintTime4(s_time, pump_last_time),
                        pump_last_volume
                        );
        lcd.print(buf);
    , если можно каждый элемент скормить lcd.print отдельно ;)

    Короче - я так вижу. Ради интереса - создайте тестовый скетч с вызовом sprintf, и без вызова sprintf для печати одного и того же текста в Serial. И посмотрите разницу - она должна быть. Также, если используется float - это жирные вычисления, отжирают много памяти, и в вашем случае, ля экономии памяти, лучше избавиться от них, перейдя на целочисленную арифметику.
     
    Daniil, Andrey12 и ИгорьК нравится это.
  3. dvanto

    dvanto Нерд

    ok. Спасибо. С уменьшением объема бинарника поиграюсь.
    sprintf использую с одним глобальным буфером
    sprintf применяю, т.к. строку вывожу на LCD и в лог

    Ключевой вопрос: как вызов read_flash() увеличивает бинарник на 150 байт?
     
    Последнее редактирование: 26 дек 2019
    Andrey12 нравится это.
  4. DIYMan

    DIYMan Guest

    Ну у вас там косвенные вызовы write_flash, внутри которого строки закатаны во флеш макросом F(). Так что всё возможно: код функции, инструкции по вызовам вложенных функций, строки во флеше - набегают лишние байты. Плюс - есть EEPROM используется только при вызове read_flash - то при использовании этой функции подлинковывается всё, что связано с работой с EEPROM - это тоже объём.

    Если уж до конца копаться - можно в ассемблерном листинге порыться, там будет видно всё.
     
    Andrey12 нравится это.
  5. dvanto

    dvanto Нерд

    EEPROM_f( get, e_offset, fv_pump.cnt ); разворачивается в
    Код (C++):
    { EEPROM.get( e_offset, fv_pump.cnt ); e_offset += sizeof(fv_pump.cnt); }
    просто, чтобы проще писать

    как в асме копаться?
    у меня hexы в темпе валяются.
    Какие средства есть?
     
  6. DIYMan

    DIYMan Guest

    Да это и так очевидно. Я про линковку говорю. Если вы нигде в коде не вызываете read_flash - то линковщик просто выкинет ненужное, и всё. И не будет работы с объектом EEPROM, который суть описан в файлах EEPROM.h и EEPROM.cpp. И не подлинкуются вызовы всяких eeprom_* функций. Код станет меньше.

    Компилятор и линковщик - не дураки, они не пихаю всё подряд в результирующий код.

    З.Ы. А ещё можно включить в настройках IDE сообщения компилятора, и полюбоваться в окне сообщений, сколько у вас будет красненьких строчек со всякими warning ;) - это компилятор бережёт ваше здоровье, предупреждая о всяких тонкостях. Но эту, безусловно, ценную инфу - по умолчанию авторы IDE держат выключенной. Чтобы не распугать никого :)
     
    Andrey12 и ИгорьК нравится это.
  7. dvanto

    dvanto Нерд

    read_flash() вызывается из setup()
    и каждый раз логирует свою работу - т.е. есть
    но вот второй вызов стоит 150б


    warning'ов нет
     
  8. vvr

    vvr Инженерище

    а вы никогда не встречались с текстами. где написано, что забивать моск дуни на 99% не есть гуд ?
    а взять дуню 328 разве сильно по карману врежет.
     
  9. parovoZZ

    parovoZZ Гуру

    Отказаться от лупов и сетупов. Там только они отожрут байт 500-700.
     
  10. dvanto

    dvanto Нерд

    мой вопрос не как оптимизировать (но за подсказки в любом случае спасибо),

    а почему один (повторный вызов) функции в бинарнике длиной 8 байт
    Код (ASM):

            0e 94 0c 0a     call    0x1418    ; 0x1418 <read_flash()>
            8f ea           ldi    r24, 0xAF    ; 175
            93 e0           ldi    r25, 0x03    ; 3
     
    приводит к росту бинарника на 150 байт

    без вызова
    Код (C++):
    000013aa <PumpOff()>:
                  80 91 f3 01     lds    r24, 0x01F3    ; 0x8001f3 <pump_last_time+0x1>
                8f 93           push    r24
                80 91 f2 01     lds    r24, 0x01F2    ; 0x8001f2 <pump_last_time>
                8f 93           push    r24
                81 e4           ldi    r24, 0x41    ; 65
                91 e0           ldi    r25, 0x01    ; 1
                9f 93           push    r25
                8f 93           push    r24
                1f 92           push    r1
                84 e0           ldi    r24, 0x04    ; 4
                8f 93           push    r24
                80 e9           ldi    r24, 0x90    ; 144
                93 e0           ldi    r25, 0x03    ; 3
                9f 93           push    r25
                8f 93           push    r24
                0e 94 3e 0d     call    0x1a7c    ; 0x1a7c <void Logging::printLevel<__FlashStringHelper const*>(int, __FlashStringHelper const*, ...) [clone .constprop.42]>
                60 e0           ldi    r22, 0x00    ; 0
                89 e0           ldi    r24, 0x09    ; 9
                0e 94 44 10     call    0x2088    ; 0x2088 <digitalWrite>
                60 e0           ldi    r22, 0x00    ; 0
                88 e0           ldi    r24, 0x08    ; 8
                0e 94 44 10     call    0x2088    ; 0x2088 <digitalWrite>
                10 92 c4 02     sts    0x02C4, r1    ; 0x8002c4 <pump>
                81 e0           ldi    r24, 0x01    ; 1
                0e 94 99 09     call    0x1332    ; 0x1332 <lcd_on(bool)>
                0e 94 71 08     call    0x10e2    ; 0x10e2 <lcd_status()>
                e9 ed           ldi    r30, 0xD9    ; 217
                f2 e0           ldi    r31, 0x02    ; 2
                20 91 f2 01     lds    r18, 0x01F2    ; 0x8001f2 <pump_last_time>
                30 91 f3 01     lds    r19, 0x01F3    ; 0x8001f3 <pump_last_time+0x1>
                84 81           ldd    r24, Z+4    ; 0x04
                95 81           ldd    r25, Z+5    ; 0x05
                a6 81           ldd    r26, Z+6    ; 0x06
                b7 81           ldd    r27, Z+7    ; 0x07
                82 0f           add    r24, r18
                93 1f           adc    r25, r19
                a1 1d           adc    r26, r1
                b1 1d           adc    r27, r1
                84 83           std    Z+4, r24    ; 0x04
                95 83           std    Z+5, r25    ; 0x05
                a6 83           std    Z+6, r26    ; 0x06
                b7 83           std    Z+7, r27    ; 0x07
                20 91 f0 01     lds    r18, 0x01F0    ; 0x8001f0 <pump_last_volume>
                30 91 f1 01     lds    r19, 0x01F1    ; 0x8001f1 <pump_last_volume+0x1>
                80 85           ldd    r24, Z+8    ; 0x08
                91 85           ldd    r25, Z+9    ; 0x09
                a2 85           ldd    r26, Z+10    ; 0x0a
                b3 85           ldd    r27, Z+11    ; 0x0b
                82 0f           add    r24, r18
                93 1f           adc    r25, r19
                a1 1d           adc    r26, r1
                b1 1d           adc    r27, r1
                80 87           std    Z+8, r24    ; 0x08
                91 87           std    Z+9, r25    ; 0x09
                a2 87           std    Z+10, r26    ; 0x0a
                b3 87           std    Z+11, r27    ; 0x0b
                0e 94 82 0f     call    0x1f04    ; 0x1f04 <write_flash(unsigned int) [clone .constprop.33]>
                8f ea           ldi    r24, 0xAF    ; 175
                93 e0           ldi    r25, 0x03    ; 3
                0e 94 00 07     call    0xe00    ; 0xe00 <Chrono::stop()>
                8d b7           in    r24, 0x3d    ; 61
                9e b7           in    r25, 0x3e    ; 62
                08 96           adiw    r24, 0x08    ; 8
                0f b6           in    r0, 0x3f    ; 63
                f8 94           cli
                9e bf           out    0x3e, r25    ; 62
                0f be           out    0x3f, r0    ; 63
                8d bf           out    0x3d, r24    ; 61
                8a eb           ldi    r24, 0xBA    ; 186
                93 e0           ldi    r25, 0x03    ; 3
                0c 94 00 07     jmp    0xe00    ; 0xe00 <Chrono::stop()>
     
    с вызовом
    Код (C++):
    0000153e <PumpOff()>:
                80 91 f3 01     lds    r24, 0x01F3    ; 0x8001f3 <pump_last_time+0x1>
                8f 93           push    r24
                80 91 f2 01     lds    r24, 0x01F2    ; 0x8001f2 <pump_last_time>
                8f 93           push    r24
                8c e6           ldi    r24, 0x6C    ; 108
                91 e0           ldi    r25, 0x01    ; 1
                9f 93           push    r25
                8f 93           push    r24
                1f 92           push    r1
                84 e0           ldi    r24, 0x04    ; 4
                8f 93           push    r24
                80 e9           ldi    r24, 0x90    ; 144
                93 e0           ldi    r25, 0x03    ; 3
                9f 93           push    r25
                8f 93           push    r24
                0e 94 d3 0d     call    0x1ba6    ; 0x1ba6 <void Logging::printLevel<__FlashStringHelper const*>(int, __FlashStringHelper const*, ...) [clone .constprop.42]>
                60 e0           ldi    r22, 0x00    ; 0
                89 e0           ldi    r24, 0x09    ; 9
                0e 94 d9 10     call    0x21b2    ; 0x21b2 <digitalWrite>
                60 e0           ldi    r22, 0x00    ; 0
                88 e0           ldi    r24, 0x08    ; 8
                0e 94 d9 10     call    0x21b2    ; 0x21b2 <digitalWrite>
                10 92 c4 02     sts    0x02C4, r1    ; 0x8002c4 <pump>
                81 e0           ldi    r24, 0x01    ; 1
                0e 94 99 09     call    0x1332    ; 0x1332 <lcd_on(bool)>
                0e 94 71 08     call    0x10e2    ; 0x10e2 <lcd_status()>
                e9 ed           ldi    r30, 0xD9    ; 217
                f2 e0           ldi    r31, 0x02    ; 2
                20 91 f2 01     lds    r18, 0x01F2    ; 0x8001f2 <pump_last_time>
                30 91 f3 01     lds    r19, 0x01F3    ; 0x8001f3 <pump_last_time+0x1>
                84 81           ldd    r24, Z+4    ; 0x04
                95 81           ldd    r25, Z+5    ; 0x05
                a6 81           ldd    r26, Z+6    ; 0x06
                b7 81           ldd    r27, Z+7    ; 0x07
                82 0f           add    r24, r18
                93 1f           adc    r25, r19
                a1 1d           adc    r26, r1
                b1 1d           adc    r27, r1
                84 83           std    Z+4, r24    ; 0x04
                95 83           std    Z+5, r25    ; 0x05
                a6 83           std    Z+6, r26    ; 0x06
                b7 83           std    Z+7, r27    ; 0x07
                20 91 f0 01     lds    r18, 0x01F0    ; 0x8001f0 <pump_last_volume>
                30 91 f1 01     lds    r19, 0x01F1    ; 0x8001f1 <pump_last_volume+0x1>
                80 85           ldd    r24, Z+8    ; 0x08
                91 85           ldd    r25, Z+9    ; 0x09
                a2 85           ldd    r26, Z+10    ; 0x0a
                b3 85           ldd    r27, Z+11    ; 0x0b
                82 0f           add    r24, r18
                93 1f           adc    r25, r19
                a1 1d           adc    r26, r1
                b1 1d           adc    r27, r1
                80 87           std    Z+8, r24    ; 0x08
                91 87           std    Z+9, r25    ; 0x09
                a2 87           std    Z+10, r26    ; 0x0a
                b3 87           std    Z+11, r27    ; 0x0b
                0e 94 17 10     call    0x202e    ; 0x202e <write_flash(unsigned int) [clone .constprop.33]>
                0e 94 0c 0a     call    0x1418    ; 0x1418 <read_flash()>
                8f ea           ldi    r24, 0xAF    ; 175
                93 e0           ldi    r25, 0x03    ; 3
                0e 94 3a 07     call    0xe74    ; 0xe74 <Chrono::stop()>
                8d b7           in    r24, 0x3d    ; 61
                9e b7           in    r25, 0x3e    ; 62
                08 96           adiw    r24, 0x08    ; 8
                0f b6           in    r0, 0x3f    ; 63
                f8 94           cli
                9e bf           out    0x3e, r25    ; 62
                0f be           out    0x3f, r0    ; 63
                8d bf           out    0x3d, r24    ; 61
                8a eb           ldi    r24, 0xBA    ; 186
                93 e0           ldi    r25, 0x03    ; 3
                0c 94 3a 07     jmp    0xe74    ; 0xe74 <Chrono::stop()>