diff --git a/examples/ADCSwitchingTest/ADCSwitchingTest.ino b/examples/ADCSwitchingTest/ADCSwitchingTest.ino index 11b3f4c..4c81605 100644 --- a/examples/ADCSwitchingTest/ADCSwitchingTest.ino +++ b/examples/ADCSwitchingTest/ADCSwitchingTest.ino @@ -53,7 +53,8 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif diff --git a/examples/AVRUtilsDemo/AVRUtilsDemo.ino b/examples/AVRUtilsDemo/AVRUtilsDemo.ino index 7761da6..6de13e8 100644 --- a/examples/AVRUtilsDemo/AVRUtilsDemo.ino +++ b/examples/AVRUtilsDemo/AVRUtilsDemo.ino @@ -50,21 +50,13 @@ || defined(__AVR_ATtiny88__) # define CODE_FOR_ATTINY #endif -#if defined(CODE_FOR_ATTINY) -#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" -#else -//#define SIZE_OF_DUMMY_ARRAY 1800 // Stack runs into data -//#define SIZE_OF_DUMMY_ARRAY 1700 // Stack is OK, but no heap is available -#define SIZE_OF_DUMMY_ARRAY 1600 // Stack is OK, and small heap is available -uint8_t sDummyArray[SIZE_OF_DUMMY_ARRAY] __attribute__((section(".noinit"))); // Place it at end of BSS to be first overwritten by stack. -#endif - -#define VERSION_EXAMPLE "1.0" +#define VERSION_EXAMPLE "1.1" #define TONE_OUT_PIN 4 #if defined(CODE_FOR_ATTINY) +#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" #define LED_PIN PB1 // Pin 1 has an LED connected on my Digispark board. # if (LED_PIN == TX_PIN) @@ -72,15 +64,24 @@ uint8_t sDummyArray[SIZE_OF_DUMMY_ARRAY] __attribute__((section(".noinit"))); // # endif #else + +//#define SIZE_OF_DUMMY_ARRAY 1800 // Stack runs into data +//#define SIZE_OF_DUMMY_ARRAY 1700 // Stack is OK, but no heap is available +#define SIZE_OF_DUMMY_ARRAY 0x600 // 1536 Stack is OK, and small heap is available +uint8_t sDummyArray[SIZE_OF_DUMMY_ARRAY] __attribute__((section(".noinit"))); // Place it at end of BSS to be first overwritten by stack. + #define LED_PIN LED_BUILTIN #endif uint8_t sMCUSRStored; // content of MCUSR register at startup + #define WATCHDOG_INFO_STRING_SIZE 16 /* * A variable to hold the reset cause written by the main program * It must not be overwritten by the initialization code after a reset. * avr-gcc provides this via the ".noinit" section. + * + * Independent of order in file, sDummyArray is allocated lower than sWatchdogResetInfoString :-( */ char sWatchdogResetInfoString[WATCHDOG_INFO_STRING_SIZE] __attribute__ ((section(".noinit"))); @@ -108,6 +109,9 @@ void setup() { * Initialize the serial pin as an output for Serial.print like debugging */ initTXPin(); + // Just to know which program is running on my Arduino + Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__)); + Serial.println(); #else /* @@ -122,34 +126,48 @@ void setup() { for (int i = 0; i < SIZE_OF_DUMMY_ARRAY; ++i) { sDummyArray[i] = 0; // Mark array with 0 to detect overwriting by StackFreeMeasurement } - initStackFreeMeasurement(); Serial.begin(115200); - -#endif // defined(CODE_FOR_ATTINY) // Just to know which program is running on my Arduino Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__)); - Serial.println(); + printBaseRAMData(&Serial); + Serial.flush(); + + initStackFreeMeasurement(); + +#endif // defined(CODE_FOR_ATTINY) + + Serial.flush(); Serial.print(F("sMCUSR=0x")); Serial.print(sMCUSRStored, HEX); - Serial.print(F(" => Boot reason is")); - printMCUSR(sMCUSRStored); + if (sMCUSRStored != 0) { + Serial.print(F(" => Boot reason is")); + printMCUSR(sMCUSRStored); + } + Serial.println(); + if (sMCUSRStored & (1 << WDRF)) { Serial.println(sWatchdogResetInfoString); } else { strncpy(sWatchdogResetInfoString, "during setup", WATCHDOG_INFO_STRING_SIZE - 1); sWatchdogResetInfoString[WATCHDOG_INFO_STRING_SIZE - 1] = '\0'; // Terminate any string later copied with strncpy(..., ..., WATCHDOG_INFO_STRING_SIZE - 1); } + Serial.flush(); printBODLevel(); + Serial.flush(); /* * Prints to avoid optimizing away the sDummyArray, which is first overwritten by stack. */ - Serial.print(F("sDummyArray[1000]=0x")); - Serial.println(sDummyArray[1000], HEX); - Serial.println(F("DummyArray size=" STR(SIZE_OF_DUMMY_ARRAY))); + sDummyArray[SIZE_OF_DUMMY_ARRAY - 1] = 0x42; + Serial.print(F("DummyArray size=" STR(SIZE_OF_DUMMY_ARRAY))); + Serial.print(F(", &DummyArray[")); + Serial.print(SIZE_OF_DUMMY_ARRAY - 1); + Serial.print(F("]=0x")); + Serial.println((uint16_t) &sDummyArray[SIZE_OF_DUMMY_ARRAY - 1], HEX); + Serial.flush(); pinMode(LED_PIN, OUTPUT); @@ -165,17 +183,29 @@ void setup() { delay(400); Serial.println(); - printRAMInfo(&Serial); - printStackUnusedAndUsedBytes(&Serial); - Serial.println(); + printRAMInfo(&Serial); + Serial.print(F("getStackMaxUsedSize=")); + Serial.println(getStackMaxUsedSize()); Serial.println(F("Dump stack / end of RAM")); - printMemoryHexDump((uint8_t*) (RAMEND - 256) + 1, 256); + printMemoryHexDump((uint8_t*) (RAMEND - 288) + 1, 288); + printRAMInfo(&Serial); Serial.println(); - printStackUsedBytes(&Serial); - Serial.println(); + + /* + * Test calloc sizes + */ + testCallocSizesAndPrint(&Serial); + + printBaseRAMData(&Serial); + printRAMInfo(&Serial); + Serial.print(F("getStackMaxUsedSize=")); + Serial.println(getStackMaxUsedSize()); // test this function, it works different from function used in printRAMInfo + + Serial.println(F("Dump stack / end of RAM")); + printMemoryHexDump((uint8_t*) (RAMEND - 288) + 1, 288); //} diff --git a/examples/AVRUtilsDemo/AVRUtilsDemo.log b/examples/AVRUtilsDemo/AVRUtilsDemo.log index 9e57cf9..fcf4ba4 100644 --- a/examples/AVRUtilsDemo/AVRUtilsDemo.log +++ b/examples/AVRUtilsDemo/AVRUtilsDemo.log @@ -1,64 +1,131 @@ START ../src/AVRUtilsDemo.cpp -Version 1.0 from Sep 11 2023 -sMCUSR=0xD5 BootReasonWasPowerUp=1 -sStaticVariable filled by analogRead(A0)=676 -sDummyArray[1000]=0x0 -DummyArray size=1800 - -Size of Data + BSS, Heap start, Stack end=2021 -Stack used 27 of 27 -Currently available Heap=0 -Stack unused=0, used=16 - -0x0880: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 -0x0890: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x40 0x02 0x66 0x04 0x40 .@.f.@ -0x08A0: 0x02 0x66 0x01 0x3C 0x1B 0x21 0x08 0x38 0x00 0x01 0x00 0x00 0x23 0xA3 0x00 0x02 .f.<...2 . #. . -0x08B0: 0x93 0x08 0xE5 0x08 0xE5 0x08 0xE4 0x01 0xEE 0x08 0xC4 0x08 0xE4 0x08 0xC0 0x08 ................ -0x08C0: 0xC0 0x00 0x00 0x03 0x3A 0x04 0x40 0x02 0x66 0x04 0x40 0x02 0x66 0x01 0x3C 0x04 . .:.@.f.@.f.<. -0x08D0: 0x40 0x00 0xD7 0x00 0x01 0x04 0x40 0x08 0xD8 0x00 0x02 0x01 0x07 0x08 0x30 0x00 @ . .@....(*.. -0x08E0: 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0xEF 0x08 0xE8 0x00 0x00 0x08 0xE0 0x07 0x15 . #. .........% -0x08F0: 0x00 0x00 0xEB 0x00 0xFB 0x38 0x7B 0x00 0x00 0x03 0x05 0x11 0x01 0x12 0x01 0x12 . .8{ ....... - -START ../src/AVRUtilsDemo.cpp -Version 1.0 from Sep 11 2023 -sMCUSR=0xD5 BootReasonWasPowerUp=1 -sStaticVariable filled by analogRead(A0)=679 -sDummyArray[1000]=0x0 -DummyArray size=1700 - -Size of Data + BSS, Heap start, Stack end=1921 -Stack used 103 of 127 -Currently available Heap=0 -Stack unused=25, used=102 - -0x0880: 0x00 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZ -0x0890: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x04 0x40 0x02 0x66 0x04 0x40 ZZZZZZZZZZ.@.f.@ -0x08A0: 0x02 0x66 0x01 0x3C 0x1F 0x25 0x08 0x38 0x00 0x01 0x00 0x00 0x23 0xA3 0x00 0x02 .f.<...2 . #. . -0x08B0: 0x93 0x08 0xE5 0x08 0xE5 0x08 0xE4 0x01 0xEE 0x08 0xC4 0x08 0xE4 0x08 0xC0 0x08 ................ -0x08C0: 0xC0 0x00 0x00 0x03 0x3A 0x04 0x40 0x02 0x66 0x04 0x40 0x02 0x66 0x01 0x3C 0x04 . .:.@.f.@.f.<. -0x08D0: 0x40 0x00 0xD7 0x00 0x01 0x04 0x40 0x08 0xD8 0x00 0x02 0x05 0x0B 0x08 0x30 0x00 @ . .@....,... -0x08E0: 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0xEF 0x08 0xE8 0x00 0x00 0x08 0xE0 0x07 0x15 . #. .........% -0x08F0: 0x00 0x00 0xEB 0x00 0xFB 0x38 0x7B 0x00 0x00 0x03 0x05 0x11 0x01 0x12 0x01 0x12 . .8{ ....... +Version 1.1 from Sep 17 2024 +__malloc_heap_start=2062|0x80E, &__heap_start=2062|0x80E, __brkval=0|0x0, __malloc_margin=128, SP=2299|0x8FB, __malloc_heap_end=0, __flp=0 +sMCUSR=0x0 +Brown-out=1.8V +DummyArray size=0x600, &DummyArray[1535]=0x7FD +Data+BSS=1806. Heap: used=0, max used=0, available=120. Stack: available=234, used=8, max used=90, unused=152 of current total 242 +Dump stack / end of RAM +0x07E0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x07F0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x42 0x64 0x75 Bdu +0x0800: 0x72 0x69 0x6E 0x67 0x20 0x73 0x65 0x74 0x75 0x70 0x00 0x00 0x00 0x00 0x5A 0x5A ring setup ZZ +0x0810: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0820: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0830: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0840: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0850: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0860: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0870: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0880: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0890: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x08A0: 0x5A 0x06 0x6F 0x03 0x23 0x01 0x5E 0x25 0x2B 0x08 0x5E 0x00 0x01 0x00 0x00 0x23 Z.o.#.^...3 . # +0x08B0: 0x00 0x00 0x03 0x55 0x08 0xE8 0x08 0xE8 0x08 0xE7 0x02 0xAA 0x08 0xC7 0x08 0xE7 . .S............ +0x08C0: 0xCA 0xD0 0x00 0x00 0x00 0x00 0x04 0x07 0x00 0x04 0x07 0x04 0x07 0x04 0x07 0x06 .. .. ....... +0x08D0: 0x6F 0x03 0x06 0x6F 0x00 0x6A 0x00 0x01 0x06 0x6F 0x08 0x6B 0x00 0x02 0x0B 0x11 o..o .o.W .o .. +0x08E0: 0x03 0x30 0x00 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0x08 0x08 0xEC 0x03 0x05 0x11 ..... . #. .Q.. +0x08F0: 0x08 0x05 0x41 0xF0 0x05 0x6F 0x01 0x02 0x01 0x0F 0x00 0x0B 0x07 0xF9 0x01 0xCC . . .{.... ..... +Data+BSS=1806. Heap: used=0, max used=0, available=120. Stack: available=234, used=8, max used=95, unused=147 of current total 242 +SP=0x8FD available=98 -> calloc(128,1)failed ->available=98 +SP=0x8FD available=98 -> calloc(64,1)=0x810 ->available=32 +SP=0x8FD available=32 -> calloc(64,1)failed ->available=32 +SP=0x8FD available=32 -> calloc(32,1)failed ->available=32 +SP=0x8FD available=32 -> calloc(16,1)=0x852 ->available=14 +SP=0x8FD available=14 -> calloc(16,1)failed ->available=14 +SP=0x8FD available=14 -> calloc(8,1)=0x864 ->available=4 +SP=0x8FD available=4 -> calloc(8,1)failed ->available=4 +SP=0x8FD available=4 -> calloc(4,1)failed ->available=4 +SP=0x8FD available=4 -> calloc(2,1)=0x86E ->available=0 +SP=0x8FD available=0 -> calloc(2,1)failed ->available=0 +SP=0x8FD available=0 -> calloc(1,1)failed -> +__malloc_heap_start=2062|0x80E, &__heap_start=2062|0x80E, __brkval=2160|0x870, __malloc_margin=128, SP=2299|0x8FB, __malloc_heap_end=0, __flp=0 +Data+BSS=1806. Heap: used=98, max used=98, available=22. Stack: available=136, used=8, max used=95, unused=49 of current total 144 +Dump stack / end of RAM +0x07E0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x07F0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x42 0x64 0x75 Bdu +0x0800: 0x72 0x69 0x6E 0x67 0x20 0x73 0x65 0x74 0x75 0x70 0x00 0x00 0x00 0x00 0x40 0x00 ring setup @ +0x0810: 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Z +0x0820: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x0830: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x0840: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x11 . +0x0850: 0x10 0x00 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 . Z +0x0860: 0x00 0x11 0x08 0x00 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x11 0x02 0x00 0x5A 0x11 .. Z .. Z. +0x0870: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0880: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0890: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x08A0: 0x5A 0x06 0x6F 0x03 0x23 0x01 0x5E 0x26 0x2C 0x08 0x38 0x00 0x01 0x00 0x00 0x23 Z.o.#.^...3 . # +0x08B0: 0x00 0x00 0x03 0x51 0x08 0xE8 0x08 0xE8 0x08 0xE7 0x02 0xAA 0x08 0xC7 0x08 0xE7 . .Q............ +0x08C0: 0xCA 0xD0 0x00 0x00 0x00 0x00 0x04 0x07 0x00 0x04 0x07 0x04 0x07 0x00 0x00 0x06 .. .. .... . +0x08D0: 0x6F 0x03 0x06 0x6F 0x00 0x6A 0x00 0x01 0x06 0x6F 0x08 0x6B 0x00 0x02 0x0C 0x12 o..o .o.W .o .. +0x08E0: 0x03 0x30 0x00 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0x08 0x08 0xEC 0x03 0x05 0x11 ..... . #. .S.. +0x08F0: 0x08 0x05 0x41 0xF0 0x05 0x6F 0x00 0x00 0x00 0x00 0x5A 0x11 0x08 0x40 0x01 0xCC . . .{ Z..@.. +Sleep 2 seconds with watchdog reset sNumberOfSleeps=0 +Sleep 2 seconds with watchdog reset sNumberOfSleeps=1 +Sleep 2 seconds with watchdog reset sNumberOfSleeps=2 +Sleep 2 seconds with watchdog reset sNumberOfSleeps=3 +Wait 5 seconds to force watchdog reset START ../src/AVRUtilsDemo.cpp -Version 1.0 from Sep 11 2023 -sMCUSR=0xD5 BootReasonWasPowerUp=1 -sStaticVariable filled by analogRead(A0)=671 -sDummyArray[1000]=0x0 -DummyArray size=1600 - -Size of Data + BSS, Heap start, Stack end=1821 -Stack used 103 of 227 -Currently available Heap=82 -Stack unused=125, used=102 +Version 1.1 from Sep 17 2024 +__malloc_heap_start=2062|0x80E, &__heap_start=2062|0x80E, __brkval=0|0x0, __malloc_margin=128, SP=2299|0x8FB, __malloc_heap_end=0, __flp=0 +sMCUSR=0x0 +Brown-out=1.8V +DummyArray size=0x600, &DummyArray[1535]=0x7FD +Data+BSS=1806. Heap: used=0, max used=0, available=120. Stack: available=234, used=8, max used=90, unused=152 of current total 242 +Dump stack / end of RAM +0x07E0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x07F0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x42 0x64 0x75 Bdu +0x0800: 0x72 0x69 0x6E 0x67 0x20 0x73 0x65 0x74 0x75 0x70 0x00 0x00 0x00 0x00 0x5A 0x5A ring setup ZZ +0x0810: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0820: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0830: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0840: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0850: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0860: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0870: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ 0x0880: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ -0x0890: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x04 0x40 0x02 0x66 0x04 0x40 ZZZZZZZZZZ.@.f.@ -0x08A0: 0x02 0x66 0x01 0x3C 0x21 0x27 0x08 0x38 0x00 0x01 0x00 0x00 0x23 0xA3 0x00 0x02 .f.<...2 . #. . -0x08B0: 0x96 0x08 0xE5 0x08 0xE5 0x08 0xE4 0x01 0xEE 0x08 0xC4 0x08 0xE4 0x08 0xC0 0x08 ................ -0x08C0: 0xC0 0x00 0x00 0x03 0x3A 0x04 0x40 0x02 0x66 0x04 0x40 0x02 0x66 0x01 0x3C 0x04 . .:.@.f.@.f.<. -0x08D0: 0x40 0x00 0xD7 0x00 0x01 0x04 0x40 0x08 0xD8 0x00 0x02 0x07 0x0D 0x08 0x30 0x00 @ . .@.....0.. -0x08E0: 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0xEF 0x08 0xE8 0x00 0x00 0x08 0xE0 0x07 0x15 . #. .........% -0x08F0: 0x00 0x00 0xEB 0x00 0x9F 0x00 0x1A 0x00 0x00 0x03 0x05 0x11 0x01 0x12 0x01 0x12 . . . ....... +0x0890: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x08A0: 0x5A 0x06 0x6F 0x03 0x23 0x01 0x5E 0x25 0x2B 0x08 0x5E 0x00 0x01 0x00 0x00 0x23 Z.o.#.^...3 . # +0x08B0: 0x00 0x00 0x03 0x55 0x08 0xE8 0x08 0xE8 0x08 0xE7 0x02 0xAA 0x08 0xC7 0x08 0xE7 . .S............ +0x08C0: 0xCA 0xD0 0x35 0x60 0x00 0x00 0x04 0x07 0x00 0x04 0x07 0x04 0x07 0x04 0x07 0x06 ..5` .. ....... +0x08D0: 0x6F 0x03 0x06 0x6F 0x00 0x6A 0x00 0x01 0x06 0x6F 0x08 0x6B 0x00 0x02 0x0B 0x11 o..o .o.W .o .. +0x08E0: 0x03 0x30 0x00 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0x08 0x08 0xEC 0x00 0x00 0x0B ..... . #. .S.. +0x08F0: 0x08 0x05 0x41 0xF0 0x05 0x6F 0x01 0x02 0x01 0x0F 0x00 0x62 0x07 0xF9 0x01 0xCC . . .{.... b.... +Data+BSS=1806. Heap: used=0, max used=0, available=120. Stack: available=234, used=8, max used=95, unused=147 of current total 242 +SP=0x8FD available=98 -> calloc(128,1)failed ->available=98 +SP=0x8FD available=98 -> calloc(64,1)=0x810 ->available=32 +SP=0x8FD available=32 -> calloc(64,1)failed ->available=32 +SP=0x8FD available=32 -> calloc(32,1)failed ->available=32 +SP=0x8FD available=32 -> calloc(16,1)=0x852 ->available=14 +SP=0x8FD available=14 -> calloc(16,1)failed ->available=14 +SP=0x8FD available=14 -> calloc(8,1)=0x864 ->available=4 +SP=0x8FD available=4 -> calloc(8,1)failed ->available=4 +SP=0x8FD available=4 -> calloc(4,1)failed ->available=4 +SP=0x8FD available=4 -> calloc(2,1)=0x86E ->available=0 +SP=0x8FD available=0 -> calloc(2,1)failed ->available=0 +SP=0x8FD available=0 -> calloc(1,1)failed -> +__malloc_heap_start=2062|0x80E, &__heap_start=2062|0x80E, __brkval=2160|0x870, __malloc_margin=128, SP=2299|0x8FB, __malloc_heap_end=0, __flp=0 +Data+BSS=1806. Heap: used=98, max used=98, available=22. Stack: available=136, used=8, max used=95, unused=49 of current total 144 +Dump stack / end of RAM +0x07E0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x07F0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x42 0x64 0x75 Bdu +0x0800: 0x72 0x69 0x6E 0x67 0x20 0x73 0x65 0x74 0x75 0x70 0x00 0x00 0x00 0x00 0x40 0x00 ring setup @ +0x0810: 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 Z +0x0820: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x0830: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 +0x0840: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x11 . +0x0850: 0x10 0x00 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 . Z +0x0860: 0x00 0x11 0x08 0x00 0x5A 0x00 0x00 0x00 0x00 0x00 0x00 0x11 0x02 0x00 0x5A 0x11 .. Z .. Z. +0x0870: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0880: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x0890: 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A 0x5A ZZZZZZZZZZZZZZZZ +0x08A0: 0x5A 0x06 0x6F 0x03 0x23 0x01 0x5E 0x26 0x2C 0x08 0x38 0x00 0x01 0x00 0x00 0x23 Z.o.#.^...3 . # +0x08B0: 0x00 0x00 0x03 0x53 0x08 0xE8 0x08 0xE8 0x08 0xE7 0x02 0xAA 0x08 0xC7 0x08 0xE7 . .S............ +0x08C0: 0xCA 0xD0 0x35 0x60 0x00 0x00 0x04 0x07 0x00 0x04 0x07 0x04 0x07 0x00 0x00 0x06 ..5` .. .... . +0x08D0: 0x6F 0x03 0x06 0x6F 0x00 0x6A 0x00 0x01 0x06 0x6F 0x08 0x6B 0x00 0x02 0x0C 0x12 o..o .o.W .o .. +0x08E0: 0x03 0x30 0x00 0x02 0x00 0x00 0x23 0x33 0x00 0x08 0x08 0x08 0xEC 0x00 0x00 0x0B ..... . #. .P.. +0x08F0: 0x08 0x05 0x41 0xF0 0x05 0x6F 0x00 0x00 0x00 0x00 0x5A 0x11 0x08 0x40 0x01 0xCC . . .{ Z..@.. +Sleep 2 seconds with watchdog reset sNumberOfSleeps=0 +Sleep 2 seconds with watchdog reset sNumberOfSleeps=1 diff --git a/examples/EMAFilterTest/EMAFilterTest.ino b/examples/EMAFilterTest/EMAFilterTest.ino index f955bf9..67d0a41 100644 --- a/examples/EMAFilterTest/EMAFilterTest.ino +++ b/examples/EMAFilterTest/EMAFilterTest.ino @@ -57,7 +57,8 @@ void setup() { pinMode(9, INPUT_PULLUP); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif diff --git a/examples/HCSR04Demo/HCSR04Demo.ino b/examples/HCSR04Demo/HCSR04Demo.ino index b798724..26a9727 100644 --- a/examples/HCSR04Demo/HCSR04Demo.ino +++ b/examples/HCSR04Demo/HCSR04Demo.ino @@ -54,7 +54,8 @@ void setup() { pinMode(USE_1_PIN_MODE_DETECTION_PIN, INPUT_PULLUP); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif diff --git a/examples/InterruptsTimings/InterruptsTimings.ino b/examples/InterruptsTimings/InterruptsTimings.ino index eec0c20..566c5bb 100644 --- a/examples/InterruptsTimings/InterruptsTimings.ino +++ b/examples/InterruptsTimings/InterruptsTimings.ino @@ -51,7 +51,8 @@ void setup() { pinMode(TEST_OUT_PIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif diff --git a/examples/VoltAndOhmmeter/VoltAndOhmmeter.ino b/examples/VoltAndOhmmeter/VoltAndOhmmeter.ino index 19a0dbe..84be159 100644 --- a/examples/VoltAndOhmmeter/VoltAndOhmmeter.ino +++ b/examples/VoltAndOhmmeter/VoltAndOhmmeter.ino @@ -130,7 +130,8 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/|| defined(SERIALUSB_PID) || defined(ARDUINO_attiny3217) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ + || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! #endif // Just to know which program is running on my Arduino diff --git a/keywords.txt b/keywords.txt index 494be27..ea192ef 100644 --- a/keywords.txt +++ b/keywords.txt @@ -31,7 +31,7 @@ readADCChannel KEYWORD2 readADCChannelWithReference KEYWORD2 readADCChannelWithOversample KEYWORD2 readADCChannelWithReferenceOversample KEYWORD2 -readADCChannelWithReferenceMultiSamples KEYWORD2 +readADCChannelMultiSamplesWithReference KEYWORD2 readADCChannelWithReferenceMax KEYWORD2 readADCChannelWithReferenceMaxMicros KEYWORD2 readUntil4ConsecutiveValuesAreEqual KEYWORD2 @@ -59,20 +59,20 @@ initPeriodicSleepWithWatchdog LITERAL1 computeSleepMillis LITERAL1 sleepWithWatchdog LITERAL1 -getHeapStart LITERAL1 -getCurrentFreeHeapOrStack LITERAL1 -getCurrentAvailableHeap LITERAL1 -printHeapStart LITERAL1 +getAvailableHeapStart LITERAL1 +getCurrentAvailableStack LITERAL1 +getCurrentAvailableHeapSize LITERAL1 +printAvailableHeapStart LITERAL1 printCurrentFreeHeap LITERAL1 printCurrentAvailableHeap LITERAL1 initStackFreeMeasurement LITERAL1 getStackUnusedBytes LITERAL1 -getStackUsedBytes LITERAL1 -getStackUnusedAndUsedBytes LITERAL1 -printStackUsedBytes LITERAL1 -printStackUnusedAndUsedBytes LITERAL1 -printStackUnusedAndUsedBytesIfChanged LITERAL1 +getStackMaxUsedBytes LITERAL1 +getStackUnusedAndMaxUsedBytes LITERAL1 +printStackMaxUsedBytes LITERAL1 +printStackUnusedAndMaxUsedBytes LITERAL1 +printStackUnusedAndMaxUsedBytesIfChanged LITERAL1 printRAMInfo LITERAL1 isAddressInRAM LITERAL1 diff --git a/src/ADCUtils.h b/src/ADCUtils.h index ce283c2..c406217 100644 --- a/src/ADCUtils.h +++ b/src/ADCUtils.h @@ -101,6 +101,12 @@ #define ADC_GND_CHANNEL_MUX 15 #define ADC_CHANNEL_MUX_MASK 0x0F +#elif defined(__AVR_ATmega644P__) +#define ADC_TEMPERATURE_CHANNEL_MUX // not existent +#define ADC_1_1_VOLT_CHANNEL_MUX 0x1E +#define ADC_GND_CHANNEL_MUX 0x1F +#define ADC_CHANNEL_MUX_MASK 0x0F + #elif defined(__AVR_ATmega32U4__) #define ADC_TEMPERATURE_CHANNEL_MUX 0x27 #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E @@ -208,7 +214,8 @@ void resetCounterForVCCUndervoltageMultipleTimes(); bool isVCCUndervoltage(); bool isVCCEmergencyUndervoltage(); bool isVCCOvervoltage(); -bool isVCCOvervoltageSimple(); +bool isVCCOvervoltageSimple(); // Version using readVCCVoltageMillivoltSimple() +bool isVCCTooHighSimple(); // Version not using readVCCVoltageMillivoltSimple() #endif // defined(__AVR__) ... diff --git a/src/ADCUtils.hpp b/src/ADCUtils.hpp index 0cff66e..73030b4 100644 --- a/src/ADCUtils.hpp +++ b/src/ADCUtils.hpp @@ -715,6 +715,7 @@ void resetCounterForVCCUndervoltageMultipleTimes() { * Raw reading of 1.1 V is 221 at 5.1 V. * Raw reading of 1.1 V is 214 at 5.25 V (+5 %). * Raw reading of 1.1 V is 204 at 5.5 V (+10 %). + * Raw reading of 1.1 V is 1126000 / VCC_MILLIVOLT * @return true if 5 % overvoltage reached */ bool isVCCOvervoltage() { @@ -726,6 +727,21 @@ bool isVCCOvervoltageSimple() { return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT); } +// Version not using readVCCVoltageMillivoltSimple() +bool isVCCTooHighSimple() { + ADMUX = ADC_1_1_VOLT_CHANNEL_MUX | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE); +// ADCSRB = 0; // Only active if ADATE is set to 1. +// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode + ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE128); // 128 -> 104 microseconds per ADC conversion at 16 MHz --- Arduino default +// wait for single conversion to finish + loop_until_bit_is_clear(ADCSRA, ADSC); + +// Get value + uint16_t tRawValue = ADCL | (ADCH << 8); + + return tRawValue < 1126000 / VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT; +} + /* * Temperature sensor is enabled by selecting the appropriate channel. * Different formula for 328P and 328PB! @@ -737,18 +753,21 @@ float getCPUTemperatureSimple(void) { return 0.0; #else // use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-( - uint16_t tTempRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2); + uint16_t tTemperatureRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2); #if defined(LOCAL_DEBUG) Serial.print(F("TempRaw=")); - Serial.println(tTempRaw); + Serial.println(tTemperatureRaw); #endif #if defined(__AVR_ATmega328PB__) - tTempRaw -= 245; - return (float)tTempRaw; + tTemperatureRaw -= 245; + return (float)tTemperatureRaw; +#elif defined(__AVR_ATtiny85__) + tTemperatureRaw -= 273; // 273 and 1.1666 are values from the datasheet + return (float)tTemperatureRaw / 1.1666; #else - tTempRaw -= 317; - return (float) tTempRaw / 1.22; + tTemperatureRaw -= 317; + return (float) tTemperatureRaw / 1.22; #endif #endif } diff --git a/src/AVRUtils.cpp b/src/AVRUtils.cpp index d99c2fc..187bde2 100644 --- a/src/AVRUtils.cpp +++ b/src/AVRUtils.cpp @@ -4,7 +4,7 @@ * Stack, Ram and Heap utilities. * Sleep utilities. * - * Copyright (C) 2016-2023 Armin Joachimsmeyer + * Copyright (C) 2016-2024 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. @@ -30,218 +30,307 @@ #include #include #include // for __malloc_margin -/* - * The largest address just not allocated so far - * Under Unix, the "break value" was the end of the data - * segment as dynamically requested from the operating system. - * Since we don't have an operating system, just make sure - * that we don't collide with the stack. - */ -extern void *__brkval; // The largest address just not allocated so far /* - * Returns actual start of free heap + * Returns actual start of available / free heap * Usage for print: - Serial.print(F("HeapStart=0x")); - Serial.println((uintptr_t) getHeapStart(), HEX); + Serial.print(F("AvailableHeapStart=0x")); + Serial.println((uint16_t) getAvailableHeapStart(), HEX); */ -uint8_t* getHeapStart(void) { +uint8_t* getAvailableHeapStart(void) { if (__brkval == 0) { - __brkval = __malloc_heap_start; + // __brkval is 0 if no malloc() has happened before +// __brkval = __malloc_heap_start; + __brkval = &__heap_start; } return (uint8_t*) __brkval; } +void printAvailableHeapStart(Print *aSerial) { + aSerial->print(F("Heap start=")); + aSerial->println((uint16_t) getAvailableHeapStart()); +} /* * Initialize RAM between current stack and actual heap start (__brkval) with pattern 0x5A */ void initStackFreeMeasurement() { - uint8_t tDummyVariableOnStack; - uint8_t *tHeapPtr = getHeapStart(); + uint8_t *tHeapPtr = getAvailableHeapStart(); // This sets __brkval // Fill / paint stack do { *tHeapPtr++ = HEAP_STACK_UNTOUCHED_VALUE; - } while (tHeapPtr < &tDummyVariableOnStack); + } while (tHeapPtr < (uint8_t*) SP); } /* - * Returns the amount of stack/heap not used/touched since the last call to initStackFreeMeasurement() - * by check for first touched pattern on the stack/heap, starting the UPWARD search at heap start. - * Sets the variable aStackUsedBytesPointer points to with amount of used/touched bytes. - * - * This fails, if a HEAP_STACK_UNTOUCHED_VALUE was written in a former malloced block. + * @return The amount of used/touched bytes since the last call to initStackFreeMeasurement() + * -1 if stack was completely used + * Check for first touched pattern on the stack/heap, starting the UPWARD search at heap start. */ -uint16_t getStackUnusedAndUsedBytes(uint16_t *aStackUsedBytesPointer) { - uint8_t tDummyVariableOnStack; - uint8_t *tHeapPtr = getHeapStart(); - -// first search for first untouched value after current begin of heap, because malloc() and free() may be happened in between and overwrite low memory - while (*tHeapPtr != HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr < &tDummyVariableOnStack) { - tHeapPtr++; +/* + * @param aStackUnusedSizePointer points to variable which is written with amount of stack/heap not used/touched. + * @return The amount of stack/heap touched since the last call to initStackFreeMeasurement() + * -1 if stack was completely used + * Do a downward search, because upward may be wrong, because malloc does not initialize the memory + * and the search fails with multiple mallocs and partial writing of allocated regions. + * Check for first two untouched pattern on the stack/heap, starting the DOWNWARD search at current stack pointer. + */ +//#include // for Serial +int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer) { + uint8_t *tAvailableHeapStart = getAvailableHeapStart(); // __brkval + uint8_t *tStackSearchPtr = (uint8_t*) SP; + + // Search for first two untouched values below current stackpointer. + // tStackSearchPtr > tAvailableHeapStart avoids overflow if stack was completely touched before. + while (!(*tStackSearchPtr == HEAP_STACK_UNTOUCHED_VALUE && *(tStackSearchPtr - 1) == HEAP_STACK_UNTOUCHED_VALUE) + && tStackSearchPtr > tAvailableHeapStart) { + tStackSearchPtr--; } -// then count untouched patterns +// Serial.println((uint16_t) tStackSearchPtr, HEX); +// Serial.println((uint16_t) tAvailableHeapStart, HEX); + /* + * tStackSearchPtr points now to highest untouched stack position + */ + int16_t tStackMaxUsedSize = RAMEND - (uint16_t) tStackSearchPtr; + + // Search for first touched value used stack. uint16_t tStackUnused = 0; - while (*tHeapPtr == HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr < &tDummyVariableOnStack) { - tHeapPtr++; + while (*tStackSearchPtr == HEAP_STACK_UNTOUCHED_VALUE && tStackSearchPtr > tAvailableHeapStart) { + tStackSearchPtr--; tStackUnused++; } - *aStackUsedBytesPointer = ((RAMEND + 1) - (uint16_t) tHeapPtr); - - return tStackUnused; + *aStackUnusedSizePointer = tStackUnused; + if (tStackUnused == 0) { + return -1; + } + return tStackMaxUsedSize; } /* - * Returns the amount of stack/heap touched since the last call to initStackFreeMeasurement() - * by check for first non touched pattern on the stack/heap, starting the DOWNWARD search at current stack pointer. - * - * If the end of former malloced and written memory was higher than current stackpointer, - * the memory area is taken as overwritten stack. Therefore we may return values, which are too big. - * But nevertheless, this constellation is likely a potential programming problem! + * Prints the amount of stack NOT used/touched and used/touched since the last call to initStackFreeMeasurement() + * Example: "Stack unused=0, used=16" if stack runs into data */ -uint16_t getStackUsedBytes() { - uint8_t tDummyVariableOnStack; - uint8_t *tHeapStart = getHeapStart(); - uint8_t *tSearchPtr = &tDummyVariableOnStack; - - // Search for first untouched value below current stackpointer - while (*tSearchPtr != HEAP_STACK_UNTOUCHED_VALUE && tSearchPtr > tHeapStart) { - tSearchPtr--; - } - - return (RAMEND + 1) - (uint16_t) tSearchPtr; +void printStackMaxUsedAndUnusedSizes(Print *aSerial) { + uint16_t tStackUnusedBytes; + aSerial->print(F("Stack used=")); + aSerial->print(RAMEND - SP); + aSerial->print(F(", max used=")); + aSerial->print(getStackMaxUsedAndUnusedSizes(&tStackUnusedBytes)); + aSerial->print(F(", unused=")); + aSerial->print(tStackUnusedBytes); + aSerial->print(F(" of current total ")); + aSerial->println((RAMEND + 1) - (uint16_t) getAvailableHeapStart()); } /* - * Returns the amount of stack/heap not touched since the last call to initStackFreeMeasurement() - * by check for first touched pattern on the stack/heap, starting the search at heap start. + * Search upwards the first two HEAP_STACK_UNTOUCHED_VALUE values after current begin of heap */ -uint16_t getStackUnusedBytes() { - uint8_t tDummyVariableOnStack; - uint8_t *tHeapPtr = getHeapStart(); - -// first search for first match after current begin of heap, because malloc() and free() may be happened in between and overwrite low memory - while (*tHeapPtr != HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr < &tDummyVariableOnStack) { +uint16_t getHeapMaxUsedSize() { + uint8_t *tHeapPtr = getAvailableHeapStart(); + while (*tHeapPtr != HEAP_STACK_UNTOUCHED_VALUE && *(tHeapPtr + 1) != HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr <= (uint8_t*) SP) { tHeapPtr++; } -// then count untouched patterns - uint16_t tStackUnused = 0; - while (*tHeapPtr == HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr < &tDummyVariableOnStack) { - tHeapPtr++; - tStackUnused++; + // tHeapPtr points now to lowest untouched stack position or to lowest current stack byte + return tHeapPtr - (uint8_t*) __malloc_heap_start; +} + +/* + * Prints the amount of stack NOT used/touched and used/touched since the last call to initStackFreeMeasurement() + * Print only if value changed. + * @return true, if values changed + */ +bool printStackMaxUsedAndUnusedSizesIfChanged(Print *aSerial) { + static int16_t tOldStackUsedBytes = 0; + + uint16_t tStackUnusedBytes; + int16_t tStackMaxUsedBytes = getStackMaxUsedAndUnusedSizes(&tStackUnusedBytes); + if (tOldStackUsedBytes != tStackMaxUsedBytes) { + tOldStackUsedBytes = tStackMaxUsedBytes; + aSerial->print(F("Stack used=")); + aSerial->print(RAMEND - SP); + aSerial->print(F(", max used=")); + aSerial->print(tStackMaxUsedBytes); + aSerial->print(F(", unused=")); + aSerial->println(tStackUnusedBytes); + return true; } - return tStackUnused; + return false; } /* - * Get amount of free RAM = current stackpointer - heap end + * Get amount of free Stack = current stackpointer - heap end */ -uint16_t getCurrentFreeHeapOrStack(void) { - uint16_t tHeapStart = (uint16_t) getHeapStart(); - if (tHeapStart >= SP) { +uint16_t getCurrentAvailableStackSize(void) { + uint16_t tAvailableHeapStart = (uint16_t) getAvailableHeapStart(); // __brkval + if (tAvailableHeapStart >= SP) { return 0; } - return (SP - (uint16_t) getHeapStart()); + return (SP - tAvailableHeapStart); +} +void printCurrentAvailableStackSize(Print *aSerial) { + aSerial->print(F("Currently available Stack[bytes]=")); + aSerial->println(getCurrentAvailableStackSize()); } /* * Get amount of maximum available memory for malloc() * FreeRam - __malloc_margin (128 for ATmega328) */ -uint16_t getCurrentAvailableHeap(void) { - if (getCurrentFreeHeapOrStack() <= __malloc_margin) { +uint16_t getCurrentAvailableHeapSize(void) { + if (getCurrentAvailableStackSize() <= (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN)) { return 0; } - return getCurrentFreeHeapOrStack() - __malloc_margin; // (128) + // SP - __brkval - (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN) + return getCurrentAvailableStackSize() - (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN); // (128) } -void printCurrentAvailableHeap(Print *aSerial) { - aSerial->print(F("Currently max available Heap[bytes]=")); - aSerial->println(getCurrentAvailableHeap()); -} - -void printHeapStart(Print *aSerial) { - aSerial->print(F("Heap start=")); - aSerial->println((uint16_t) getHeapStart()); +void printCurrentAvailableHeapSize(Print *aSerial) { + aSerial->print(F("Currently available Heap[bytes]=")); + aSerial->println(getCurrentAvailableHeapSize()); } /* - * Prints the amount of stack used/touched since the last call to initStackFreeMeasurement() - * Example: "Stack used 20 of 7" up to "Stack used 20 of 20" if stack runs into data + * Simple and short implementation, does not work before initStackFreeMeasurement() or first malloc() + * The STACK required for this function is 4 bytes, so available numbers are 4 less than for caller. */ -void printStackUsedBytes(Print *aSerial) { - aSerial->print(F("Stack used ")); - aSerial->print(getStackUsedBytes()); - aSerial->print(F(" of ")); - aSerial->println((RAMEND + 1) - (uint16_t) getHeapStart()); +void printCurrentAvailableHeapSizeSimple(Print *aSerial) { + aSerial->print(F("available=")); + aSerial->println(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN)); } -/* - * Prints the amount of stack NOT used/touched and used/touched since the last call to initStackFreeMeasurement() - * Example: "Stack unused=0, used=16" if stack runs into data - */ -void printStackUnusedAndUsedBytes(Print *aSerial) { - uint16_t tStackUsedBytes; - aSerial->print(F("Stack unused=")); - aSerial->print(getStackUnusedAndUsedBytes(&tStackUsedBytes)); - aSerial->print(F(", used=")); - aSerial->println(tStackUsedBytes); -} +// This define is in AVRUtils.h +// #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN)) -/* - * Prints the amount of stack NOT used/touched and used/touched since the last call to initStackFreeMeasurement() - * Print only if value changed. - */ -void printStackUnusedAndUsedBytesIfChanged(Print *aSerial) { - static uint16_t sStackUsedBytes = 0; - - uint16_t tOldStackUsedBytes = sStackUsedBytes; - uint16_t tStackUnusedBytes = getStackUnusedAndUsedBytes(&sStackUsedBytes); - if (tOldStackUsedBytes != sStackUsedBytes) { - aSerial->print(F("Stack unused=")); - aSerial->print(tStackUnusedBytes); - aSerial->print(F(", used=")); - aSerial->println(sStackUsedBytes); - } -} +void printBaseRAMData(Print *aSerial) { + aSerial->print(F("__malloc_heap_start=")); + aSerial->print((uint16_t) __malloc_heap_start); // = __bss_end, __heap_start in lst file + aSerial->print(F("|0x")); + aSerial->print((uint16_t) __malloc_heap_start, HEX); + + aSerial->print(F(", &__heap_start=")); + aSerial->print((uint16_t) &__heap_start); + aSerial->print(F("|0x")); + aSerial->print((uint16_t) &__heap_start, HEX); + + aSerial->print(F(", __brkval=")); + aSerial->print((uint16_t) __brkval); // The largest address just not allocated so far / start of available / free heap, initialized at first malloc() + aSerial->print(F("|0x")); + aSerial->print((uint16_t) __brkval, HEX); + aSerial->print(F(", __malloc_margin=")); + aSerial->print((uint16_t) __malloc_margin); // =128 + + aSerial->print(F(", SP=")); + aSerial->print((uint16_t) SP); + aSerial->print(F("|0x")); + aSerial->print((uint16_t) SP, HEX); + + /* + * The next 2 entries seems to be always 0 + */ + aSerial->print(F(", __malloc_heap_end=")); + aSerial->print((uint16_t) __malloc_heap_end); + + aSerial->print(F(", __flp=")); + aSerial->print((uint16_t) __flp); // The largest address just not allocated so far / start of available / free heap, initialized at first malloc() + aSerial->println(); +} /* - * RAM starts of variables initialized with values != 0, - * followed by variables initialized with 0 + * RAM starts with Data, i.e. variables initialized with values != 0, + * followed by BSS, i.e. uninitalized variables (which are initialized with 0) * and variables not initialized by using attribute "__attribute__((section(".noinit")))". * It ends with the heap and the stack. * - * Sample output if stack runs into data: - * Size of Data + BSS, Heap start, Stack end=2041 - * Stack used 20 of 7 - * Currently available Heap=0 + * The STACK required for this function is 8 bytes, so available numbers are 8 less than for caller. + * + * Sample output: + * Data+BSS=445. Heap: used=770, max used=1096, available=663. Stack: available=791, used=42, max used=319, unused=188 of current total 833 + * Formulas: + * Stack available + used = current total + * Heap available + __malloc_margin (128) = Stack available + * Data+BSS + Heap max used + Stack unused + Stack max used = RAMSIZE */ void printRAMInfo(Print *aSerial) { - uint16_t tHeapStart = (uint16_t) getHeapStart(); - aSerial->print(F("Size of Data + BSS, Heap start, Stack end=0x")); - aSerial->print(tHeapStart - RAMSTART, HEX); - aSerial->print(F(" | ")); - aSerial->println(tHeapStart - RAMSTART); - printStackUsedBytes(aSerial); + aSerial->print(F("Data+BSS=")); + aSerial->print((uint16_t) &__heap_start - RAMSTART); + + aSerial->print(F(". Heap: used=")); + aSerial->print((uint16_t) getAvailableHeapStart() - (uint16_t) &__heap_start); + aSerial->print(F(", max used=")); + aSerial->print(getHeapMaxUsedSize()); + aSerial->print(F(", available=")); + uint16_t tStackAvailable = SP - (uint16_t) getAvailableHeapStart() + 1; + aSerial->print(tStackAvailable - (uint16_t) __malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN); - aSerial->print(F("Currently available Heap=")); - aSerial->println(getCurrentAvailableHeap()); + aSerial->print(F(". Stack: available=")); + aSerial->print(tStackAvailable); + aSerial->print(F(", used=")); + aSerial->print(RAMEND - SP); + uint16_t tStackUnusedBytes; + aSerial->print(F(", max used=")); + aSerial->print(getStackMaxUsedAndUnusedSizes(&tStackUnusedBytes)); + aSerial->print(F(", unused=")); + aSerial->print(tStackUnusedBytes); + aSerial->print(F(" of current total ")); + aSerial->print((RAMEND + 1) - (uint16_t) getAvailableHeapStart()); // getAvailableHeapStart() + + aSerial->println(); +} + +void set__malloc_margin(uint8_t aNewMallocMargin) { + __malloc_margin = aNewMallocMargin; } -void printCurrentFreeHeap(Print *aSerial) { - aSerial->print(F("Current free Heap / Stack[bytes]=")); - aSerial->println(getCurrentFreeHeapOrStack()); +void reset__malloc_margin() { + __malloc_margin = 128; } bool isAddressInRAM(void *aAddressToCheck) { return (aAddressToCheck <= (void*) RAMEND); } -bool isAddressBelowHeap(void *aAddressToCheck) { - return (aAddressToCheck < getHeapStart()); +bool isAddressBelowAvailableHeapStart(void *aAddressToCheck) { + return (aAddressToCheck < getAvailableHeapStart()); } +/* + * Test available heap by callocing 128 bytes chunks, + * If no memory available, try with 64, 32 etc up to 2, 1 byte chunks + */ +void testCallocSizesAndPrint(Print *aSerial) { + uint8_t *tLastMallocPtr; + uint16_t tMallocSize = 128; + while (true) { + aSerial->print(F("SP=0x")); + aSerial->print(SP, HEX); + aSerial->print(F(" available=")); + aSerial->print(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN)); + uint8_t *tMallocPtr = (uint8_t*) calloc(tMallocSize, 1); + + aSerial->print(F(" -> calloc(")); + aSerial->print(tMallocSize); + aSerial->print(F(",1)")); + + if (tMallocPtr == NULL) { + aSerial->print(F("failed ->")); + tMallocSize = tMallocSize >> 1; + if (tMallocSize < 1) { + aSerial->println(); + break; + } + } else { + tLastMallocPtr = tMallocPtr; + aSerial->print(F("=0x")); + aSerial->print((uint16_t) tLastMallocPtr, HEX); + aSerial->print(F(" ->")); + + *tLastMallocPtr = HEAP_STACK_UNTOUCHED_VALUE; // For testing detection using 2 consecutive HEAP_STACK_UNTOUCHED_VALUE + *(tLastMallocPtr + tMallocSize - 1) = 0x11; + } + printCurrentAvailableHeapSizeSimple(aSerial); + } +} /******************************************** * SLEEP AND WATCHDOG STUFF ********************************************/ diff --git a/src/AVRUtils.h b/src/AVRUtils.h index 7ed790b..32a9bf5 100644 --- a/src/AVRUtils.h +++ b/src/AVRUtils.h @@ -1,7 +1,7 @@ /* * AVRUtils.h * - * Copyright (C) 2016-2020 Armin Joachimsmeyer + * Copyright (C) 2016-2024 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. @@ -29,6 +29,18 @@ #include #include "avr/boot.h" +/* + * The largest address just not allocated so far + * Under Unix, the "break value" was the end of the data + * segment as dynamically requested from the operating system. + * Since we don't have an operating system, just make sure + * that we don't collide with the stack. + */ +extern void *__brkval; // The largest address just not allocated so far / start of available / free heap, initialized at first malloc() +extern void *__flp; // +extern char __heap_start; // = __bss_end, the linker address of heap start +#define HEURISTIC_ADDITIONAL_MALLOC_MARGIN 14 // No malloc() possible if size is lower than (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN) + /* * storage for millis value to enable compensation for interrupt disable at signal acquisition etc. */ @@ -55,26 +67,32 @@ extern volatile uint16_t sNumberOfSleeps; #include -uint8_t* getHeapStart(); -uint16_t getCurrentFreeHeapOrStack(void); -uint16_t getCurrentAvailableHeap(void); -void printHeapStart(Print *aSerial); -void printCurrentFreeHeap(Print *aSerial); -void printCurrentAvailableHeap(Print *aSerial); +uint8_t* getAvailableHeapStart(); +void printAvailableHeapStart(Print *aSerial); +uint16_t getCurrentAvailableStackSize(void); +void printCurrentAvailableStackSize(Print *aSerial); +uint16_t getCurrentAvailableHeapSize(void); +void printCurrentAvailableHeapSize(Print *aSerial); +void printCurrentAvailableHeapSizeSimple(Print *aSerial); +#define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN)) #define HEAP_STACK_UNTOUCHED_VALUE 0x5A void initStackFreeMeasurement(); -uint16_t getStackUnusedBytes(); -uint16_t getStackUsedBytes(); -uint16_t getStackUnusedAndUsedBytes(uint16_t *aStackUsedBytesPointer); -void printStackUsedBytes(Print *aSerial); -void printStackUnusedAndUsedBytes(Print *aSerial); -void printStackUnusedAndUsedBytesIfChanged(Print *aSerial); +int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer); +void printStackMaxUsedAndUnusedSizes(Print *aSerial); +bool printStackMaxUsedAndUnusedSizesIfChanged(Print *aSerial); + +void printBaseRAMData(Print *aSerial); void printRAMInfo(Print *aSerial); bool isAddressInRAM(void *aAddressToCheck); -bool isAddressBelowHeap(void *aAddressToCheck); +bool isAddressBelowAvailableHeapStart(void *aAddressToCheck); + +void set__malloc_margin(uint8_t aNewMallocMargin); +void reset__malloc_margin(); + +void testCallocSizesAndPrint(Print *aSerial); #endif // defined(__AVR__) #endif // _AVR_UTILS_H diff --git a/src/DebugLevel.h b/src/DebugLevel.h index e8223b8..e86a9f4 100644 --- a/src/DebugLevel.h +++ b/src/DebugLevel.h @@ -1,8 +1,15 @@ /* * DebugLevel.h - * Include to propagate debug levels + * Include to propagate debug levels to each other * - * Copyright (C) 2016-2020 Armin Joachimsmeyer + * TRACE // Information you need to understand details of a function or if you hunt a bug. + * DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. + * INFO // Information you want to see in regular operation to see what the program is doing. E.g. "Now playing Muppets melody". + * WARN // Information that the program may encounter problems, like small Heap/Stack area. + * ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. + * + * + * Copyright (C) 2016-2024 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. @@ -25,7 +32,7 @@ #ifndef _DEBUGLEVEL_H #define _DEBUGLEVEL_H -// Propagate debug level +// Propagate different debug level #if defined(TRACE) // Information you need to understand details of a function or if you hunt a bug. # if !defined(DEBUG) #define DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. diff --git a/src/HCSR04.hpp b/src/HCSR04.hpp index b700511..5317f08 100644 --- a/src/HCSR04.hpp +++ b/src/HCSR04.hpp @@ -70,7 +70,15 @@ //#define USE_PIN_CHANGE_INTERRUPT_D0_TO_D7 // using PCINT2_vect - PORT D //#define USE_PIN_CHANGE_INTERRUPT_D8_TO_D13 // using PCINT0_vect - PORT B - Pin 13 is feedback output //#define USE_PIN_CHANGE_INTERRUPT_A0_TO_A5 // using PCINT1_vect - PORT C +#if __has_include("digitalWriteFast.h") #include "digitalWriteFast.h" +#else +#define pinModeFast pinMode +#define digitalReadFast digitalRead +#define digitalWriteFast digitalWrite +#define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P)) +#endif + #include "HCSR04.h" //#define DEBUG @@ -132,6 +140,7 @@ void initUSDistancePin(uint8_t aTriggerOutEchoInPin) { #if !defined (TRIGGER_OUT_PIN) sTriggerOutPin = aTriggerOutEchoInPin; #endif + (void) aTriggerOutEchoInPin; sHCSR04Mode = HCSR04_MODE_USE_1_PIN; } diff --git a/src/HexDump.hpp b/src/HexDump.hpp index def5733..b3b8d45 100644 --- a/src/HexDump.hpp +++ b/src/HexDump.hpp @@ -108,10 +108,10 @@ void printMemoryHexDump(uint8_t *aMemory, uint16_t aNumberOfBytesToPrint, uint8_ */ Serial.print(F(" ")); for (uint_fast8_t i = 0; i < aBytesPerLine; i++) { - char tCharacterToPrint = aMemory[tIndex + i]; + uint8_t tCharacterToPrint = aMemory[tIndex + i]; // if(isalnum(tIndex+i)){ // requires 40 bytes more program space if (' ' <= tCharacterToPrint && tCharacterToPrint <= '~') { - Serial.print(tCharacterToPrint); + Serial.print((char)tCharacterToPrint); } else if (tCharacterToPrint != 0x00 && tCharacterToPrint != 0xFF) { // for non printable characters except 0 and FF Serial.print('.'); diff --git a/src/LongUnion.h b/src/LongUnion.h index 3559ac2..8f90f61 100644 --- a/src/LongUnion.h +++ b/src/LongUnion.h @@ -87,7 +87,7 @@ union LongUnion { struct { WordUnion LowWord; WordUnion HighWord; - } WordUnion; + } TwoWordUnions; uint8_t UBytes[4]; // seems to have the same code size as using struct UByte int8_t Bytes[4]; // Bytes[0] is LowByte uint16_t UWords[2]; @@ -122,7 +122,7 @@ union LongLongUnion { WordUnion MidLowWord; WordUnion MidHighWord; WordUnion HighWord; - } WordUnion; + } FourWordUnions; struct { uint32_t LowLong; uint32_t HighLong; @@ -134,7 +134,7 @@ union LongLongUnion { struct { LongUnion LowLong; LongUnion HighLong; - } LongUnion; + } TwoLongUnions; uint8_t UBytes[8]; // seems to have the same code size as using struct UByte int8_t Bytes[8]; uint16_t UWords[4]; diff --git a/src/ShowInfo.cpp b/src/ShowInfo.cpp index a45cf55..e61e1fa 100644 --- a/src/ShowInfo.cpp +++ b/src/ShowInfo.cpp @@ -76,24 +76,6 @@ float GetTemp(void) { return (t); } -// Helper function for free ram. -// With use of http://playground.arduino.cc/Code/AvailableMemory -// -int freeRam(void) { - extern unsigned int __heap_start; - extern void *__brkval; - - int free_memory; - int stack_here; - - if (__brkval == 0) - free_memory = (int) &stack_here - (int) &__heap_start; - else - free_memory = (int) &stack_here - (int) __brkval; - - return (free_memory); -} - // Helper function for sketch size. // The sketch size is runtime calculated. // From user "Coding Badly" in his post: @@ -114,7 +96,6 @@ unsigned long sketchSize(void) { void Information(void) { #if !defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny87__) - int i, j; int data1, data2, data3, data4; unsigned long ul; float percentage; @@ -131,17 +112,6 @@ void Information(void) { percentage = (float) ul / ((float) FLASHEND + 1.0) * 100.0; Serial.print(percentage, 0); Serial.println(F("%)")); - - Serial.print(F("free RAM = ")); - i = freeRam(); - Serial.println(i, DEC); - Serial.print(F("RAM used = ")); - j = (RAMEND + 1) - i; - Serial.print(j, DEC); - Serial.print(F(" (")); - percentage = (float) j / ((float) RAMEND + 1.0) * 100.0; - Serial.print(percentage, 0); - Serial.println(F("%)")); #endif #if defined(ARDUINO) diff --git a/src/digitalWriteFast.h b/src/digitalWriteFast.h index 1bb8eb5..a36a71f 100644 --- a/src/digitalWriteFast.h +++ b/src/digitalWriteFast.h @@ -11,6 +11,14 @@ #ifndef __digitalWriteFast_h_ #define __digitalWriteFast_h_ 1 +//#define THROW_ERROR_IF_NOT_FAST // If activated, an error is thrown if pin is not a compile time constant +void NonConstantsUsedForPinModeFast( void ) __attribute__ (( error("Parameter for pinModeFast() function is not constant") )); +void NonConstantsUsedForDigitalWriteFast( void ) __attribute__ (( error("Parameter for digitalWriteFast() function is not constant") )); +void NonConstantsUsedForDigitalToggleFast( void ) __attribute__ (( error("Parameter for digitalToggleFast() function is not constant") )); +int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Parameter for digitalReadFast() function is not constant") )); + +#if !defined(MEGATINYCORE) // megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast(). + //#define SANGUINO_PINOUT // define for Sanguino pinout // general macros/defines @@ -312,12 +320,6 @@ #endif - -void NonConstantsUsedForPinModeFast( void ) __attribute__ (( error("Parameter for pinModeFast() function is not constant") )); -void NonConstantsUsedForDigitalWriteFast( void ) __attribute__ (( error("Parameter for digitalWriteFast() function is not constant") )); -void NonConstantsUsedForDigitalToggleFast( void ) __attribute__ (( error("Parameter for digitalToggleFast() function is not constant") )); -int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Parameter for digitalReadFast() function is not constant") )); - #if !defined(digitalWriteFast) # if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg) # if defined(THROW_ERROR_IF_NOT_FAST) @@ -416,4 +418,5 @@ if (__builtin_constant_p(P)) { \ # endif #endif // !defined(digitalToggleFast) +#endif // !defined(MEGATINYCORE) #endif //__digitalWriteFast_h_