4242
4343uint8_t * getStartOfAvailableHeap (void ) {
4444 if (__brkval == 0 ) {
45- // __brkval is 0 if no malloc() has happened before
45+ // __brkval is 0 if no malloc() has happened before
4646// __brkval = __malloc_heap_start;
47- __brkval = &__heap_start;
47+ __brkval = &__heap_start; // = __bss_end, the linker address of heap start
4848 }
4949 return (uint8_t *) __brkval;
5050}
@@ -87,7 +87,7 @@ int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer) {
8787 tStackUnused++;
8888 }
8989
90- int16_t tStackMaxUsedSize = (RAMEND + 1 ) - (uint16_t ) tHeapPtr;
90+ int16_t tStackMaxUsedSize = (RAMEND + 1 ) - (int16_t ) tHeapPtr;
9191
9292 *aStackUnusedSizePointer = tStackUnused;
9393 if (tStackUnused == 0 ) {
@@ -109,17 +109,25 @@ void printStackMaxUsedAndUnusedSizes(Print *aSerial) {
109109 aSerial->print (F (" , unused=" ));
110110 aSerial->print (tStackUnusedBytes);
111111 aSerial->print (F (" of current total " ));
112- aSerial->println ((RAMEND + 1 ) - (uint16_t ) getStartOfAvailableHeap ());
112+ aSerial->println ((RAMEND + 1 ) - (int16_t ) getStartOfAvailableHeap ());
113113}
114114
115115/*
116116 * Search upwards the first two HEAP_STACK_UNTOUCHED_VALUE values after current begin of heap
117+ * If stack uses total heap, we see the current available stack size here :-(
117118 */
118- uint16_t getHeapMaxUsedSize () {
119+ int16_t getHeapMaxUsedSize () {
119120 uint8_t *tHeapPtr = getStartOfAvailableHeap ();
120121 while (*tHeapPtr != HEAP_STACK_UNTOUCHED_VALUE && *(tHeapPtr + 1 ) != HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr <= (uint8_t *) SP) {
121122 tHeapPtr++;
122123 }
124+ // Serial.print(F("tHeapPtr=0x"));
125+ // Serial.print((uint16_t)tHeapPtr, HEX);
126+ // Serial.print(F(" SP=0x"));
127+ // Serial.println((uint16_t)SP, HEX);
128+ if ((tHeapPtr-1 ) == (uint8_t *) SP) {
129+ return -1 ;
130+ }
123131 // tHeapPtr points now to lowest untouched stack position or to lowest current stack byte
124132 return tHeapPtr - (uint8_t *) __malloc_heap_start;
125133}
@@ -185,7 +193,7 @@ uint16_t getTheoreticalMaximumAvailableHeapSize(void) {
185193 if (RAMEND <= __malloc_margin) {
186194 return 0 ;
187195 }
188- return (RAMEND - RAMSTART) -__malloc_margin; // (128)
196+ return (RAMEND - RAMSTART) - __malloc_margin; // (128)
189197}
190198
191199/*
@@ -202,11 +210,11 @@ void printCurrentAvailableHeapSize(Print *aSerial) {
202210 */
203211void printCurrentAvailableHeapSizeSimple (Print *aSerial) {
204212 aSerial->print (F (" available=" ));
205- aSerial->println (SP - (uint16_t ) __brkval + 1 - ((uint16_t ) __malloc_margin));
213+ aSerial->println (SP - (int16_t ) __brkval + 1 - ((int16_t ) __malloc_margin));
206214}
207215
208216// This define is in AVRUtils.h
209- // #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t ) __brkval + 1 - HEURISTIC_ADDITIONAL_MALLOC_MARGIN - ((uint16_t ) __malloc_margin))
217+ // #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (int16_t ) __brkval + 1 - HEURISTIC_ADDITIONAL_MALLOC_MARGIN - ((int16_t ) __malloc_margin))
210218
211219void printBaseRAMData (Print *aSerial) {
212220 // __malloc_heap_end seems to be 0
@@ -259,32 +267,36 @@ void printBaseRAMData(Print *aSerial) {
259267 * Heap available + __malloc_margin (128) = Stack available
260268 * Data+BSS + Heap max used + Stack unused + Stack max used = RAMSIZE
261269 */
262- void printRAMInfo (Print *aSerial) {
270+ void printRAMAndStackInfo (Print *aSerial) {
263271
264272 aSerial->print (F (" Data+BSS=" ));
265- aSerial->print ((uint16_t ) &__heap_start - RAMSTART);
273+ aSerial->print ((int16_t ) &__heap_start - RAMSTART);
266274
267275 aSerial->print (F (" . Heap: used=" ));
268- aSerial->print ((uint16_t ) getStartOfAvailableHeap () - (uint16_t ) &__heap_start);
269- aSerial->print (F (" , max written=" )); // if Stack uses total heap, we see the stack size here :-(
276+ aSerial->print ((uint16_t ) getStartOfAvailableHeap () - (int16_t ) &__heap_start);
277+ aSerial->print (F (" , max written=" )); // If stack uses total heap, we see the stack size here :-(
270278 aSerial->print (getHeapMaxUsedSize ());
271279 aSerial->print (F (" , max available=" ));
272- aSerial->print (RAMEND - (uint16_t ) getStartOfAvailableHeap () + 1 - (uint16_t ) __malloc_margin);
280+ aSerial->print (RAMEND - (int16_t ) getStartOfAvailableHeap () + 1 - (int16_t ) __malloc_margin);
273281
274282 aSerial->print (F (" . Stack: available=" ));
275- aSerial->print (SP - (uint16_t ) getStartOfAvailableHeap () + 1 );
283+ aSerial->print (( SP + 1 ) - (int16_t ) getStartOfAvailableHeap ());
276284 aSerial->print (F (" , used=" ));
277285 aSerial->print (RAMEND - SP);
286+
278287 uint16_t tStackUnusedBytes;
279288 aSerial->print (F (" , max used=" ));
280289 aSerial->print (getStackMaxUsedAndUnusedSizes (&tStackUnusedBytes));
281290 aSerial->print (F (" , unused=" ));
282291 aSerial->print (tStackUnusedBytes);
283292 aSerial->print (F (" of current total " ));
284- aSerial->print ((RAMEND + 1 ) - (uint16_t ) getStartOfAvailableHeap ()); // getStartOfAvailableHeap()
293+ aSerial->print ((RAMEND + 1 ) - (int16_t ) getStartOfAvailableHeap ()); // getStartOfAvailableHeap()
285294
286295 aSerial->println ();
287296}
297+ void printRAMInfo (Print *aSerial) {
298+ printRAMAndStackInfo (aSerial);
299+ }
288300
289301/*
290302 * The minimal margin from Heap End to to Stack Start for malloc()
@@ -317,9 +329,9 @@ void testCallocSizesAndPrint(Print *aSerial) {
317329 aSerial->print (F (" SP=0x" ));
318330 aSerial->print (SP, HEX);
319331 aSerial->print (F (" available=" ));
320- aSerial->print (SP - (uint16_t ) __brkval + 1 - ((uint16_t ) __malloc_margin)- HEURISTIC_ADDITIONAL_MALLOC_MARGIN);
332+ aSerial->print (SP - (int16_t ) __brkval + 1 - ((int16_t ) __malloc_margin) - HEURISTIC_ADDITIONAL_MALLOC_MARGIN);
321333 aSerial->print (F (" max available=" ));
322- aSerial->print (RAMEND - (uint16_t ) __brkval + 1 - ((uint16_t ) __malloc_margin));
334+ aSerial->print (RAMEND - (int16_t ) __brkval + 1 - ((int16_t ) __malloc_margin));
323335 uint8_t *tMallocPtr = (uint8_t *) calloc (tMallocSize, 1 );
324336
325337 aSerial->print (F (" -> calloc(" ));
@@ -377,7 +389,7 @@ void initSleep(uint8_t tSleepMode) {
377389}
378390
379391/*
380- * Watchdog wakes CPU periodically and all we have to do is call sleep_cpu();
392+ * Watchdog wakes CPU periodically and all we have to do is call sleep_cpu() - see AVRUtilsDemo
381393 * aWatchdogPrescaler (see wdt.h) can be one of
382394 * WDTO_15MS, 30, 60, 120, 250, WDTO_500MS
383395 * WDTO_1S to WDTO_8S
@@ -399,6 +411,27 @@ void initPeriodicSleepWithWatchdog(uint8_t tSleepMode, uint8_t aWatchdogPrescale
399411 WDTCSR = tWDTCSR; // set final Value
400412}
401413
414+ /*
415+ * Watchdog interrupts CPU periodically and ISR can be used to handle timeout - see AVRUtilsDemo
416+ * The reason for timeout is NOT removed, i.e. an endless loop will not be exited.
417+ * aWatchdogPrescaler (see wdt.h) can be one of
418+ * WDTO_15MS, 30, 60, 120, 250, WDTO_500MS
419+ * WDTO_1S to WDTO_8S
420+ */
421+ void initTimeoutWithWatchdog (uint8_t aWatchdogPrescaler) {
422+ MCUSR = ~_BV (WDRF); // Clear WDRF in MCUSR
423+
424+ #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) \
425+ || defined (__AVR_ATtiny24__) || defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) \
426+ || defined (__AVR_ATtiny87__) || defined (__AVR_ATtiny167__)
427+ #define WDTCSR WDTCR
428+ #endif
429+ // Watchdog interrupt enable + reset interrupt flag -> needs ISR(WDT_vect)
430+ uint8_t tWDTCSR = _BV (WDIE) | _BV (WDIF) | (aWatchdogPrescaler & 0x08 ? _WD_PS3_MASK : 0x00 ) | (aWatchdogPrescaler & 0x07 ); // handles that the WDP3 bit is in bit 5 of the WDTCSR register,
431+ WDTCSR = _BV (WDCE) | _BV (WDE); // clear lock bit for 4 cycles by writing 1 to WDCE AND WDE
432+ WDTCSR = tWDTCSR; // set final Value
433+ }
434+
402435/*
403436 * @param aWatchdogPrescaler (see wdt.h) can be one of WDTO_15MS, 30, 60, 120, 250, WDTO_500MS, WDTO_1S to WDTO_8S
404437 * 0 (15 ms) to 3(120 ms), 4 (250 ms) up to 9 (8000 ms)
@@ -455,6 +488,15 @@ void sleepWithWatchdog(uint8_t aWatchdogPrescaler, bool aAdjustMillis) {
455488 }
456489}
457490
491+ /*
492+ * Sample ISR for Watchdog
493+ * This interrupt prints the timeout message
494+ */
495+ // ISR(WDT_vect) {
496+ // wdt_reset();
497+ // myLCD.setCursor(0, 3);
498+ // myLCD.print(F("No voltage detected "));
499+ // }
458500/*
459501 * 0 -> %1
460502 * _BV(CLKPS0) -> %2
0 commit comments