Беда... Написал программу управления насосом Стал прикручивать 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; } } скетч приложил файлом - он большой
Что предлагаю сходу: 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 - это жирные вычисления, отжирают много памяти, и в вашем случае, ля экономии памяти, лучше избавиться от них, перейдя на целочисленную арифметику.
ok. Спасибо. С уменьшением объема бинарника поиграюсь. sprintf использую с одним глобальным буфером sprintf применяю, т.к. строку вывожу на LCD и в лог Ключевой вопрос: как вызов read_flash() увеличивает бинарник на 150 байт?
Ну у вас там косвенные вызовы write_flash, внутри которого строки закатаны во флеш макросом F(). Так что всё возможно: код функции, инструкции по вызовам вложенных функций, строки во флеше - набегают лишние байты. Плюс - есть EEPROM используется только при вызове read_flash - то при использовании этой функции подлинковывается всё, что связано с работой с EEPROM - это тоже объём. Если уж до конца копаться - можно в ассемблерном листинге порыться, там будет видно всё.
EEPROM_f( get, e_offset, fv_pump.cnt ); разворачивается в Код (C++): { EEPROM.get( e_offset, fv_pump.cnt ); e_offset += sizeof(fv_pump.cnt); } просто, чтобы проще писать как в асме копаться? у меня hexы в темпе валяются. Какие средства есть?
Да это и так очевидно. Я про линковку говорю. Если вы нигде в коде не вызываете read_flash - то линковщик просто выкинет ненужное, и всё. И не будет работы с объектом EEPROM, который суть описан в файлах EEPROM.h и EEPROM.cpp. И не подлинкуются вызовы всяких eeprom_* функций. Код станет меньше. Компилятор и линковщик - не дураки, они не пихаю всё подряд в результирующий код. З.Ы. А ещё можно включить в настройках IDE сообщения компилятора, и полюбоваться в окне сообщений, сколько у вас будет красненьких строчек со всякими warning - это компилятор бережёт ваше здоровье, предупреждая о всяких тонкостях. Но эту, безусловно, ценную инфу - по умолчанию авторы IDE держат выключенной. Чтобы не распугать никого
read_flash() вызывается из setup() и каждый раз логирует свою работу - т.е. есть но вот второй вызов стоит 150б warning'ов нет
а вы никогда не встречались с текстами. где написано, что забивать моск дуни на 99% не есть гуд ? а взять дуню 328 разве сильно по карману врежет.
мой вопрос не как оптимизировать (но за подсказки в любом случае спасибо), а почему один (повторный вызов) функции в бинарнике длиной 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()>