Skip to content

Commit

Permalink
V2
Browse files Browse the repository at this point in the history
  • Loading branch information
Trusty77 committed Aug 5, 2015
1 parent 1feb5ef commit edfc986
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 53 deletions.
72 changes: 72 additions & 0 deletions MemoryUsage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
MemoryUsage.c - MemoryUsage library
Copyright (c) 2015 Thierry Paris. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "Arduino.h"
#include "MemoryUsage.h"

// Thanks to adafruit : https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory
int mu_freeRam()
{
//extern int __heap_start, *__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval);
}

// Copy / adaptation of the library StackPaint available here : https://github.com/WickedDevice/StackPaint

#define STACK_CANARY 0xc5

void mu_StackPaint(void) __attribute__((naked)) __attribute__((section(".init1")));

void mu_StackPaint(void)
{
#if 1
uint8_t *p = &_end;

while (p <= &__stack)
{
*p = STACK_CANARY;
p++;
}
#else
__asm volatile (
" ldi r30,lo8(_end)\n"
" ldi r31,hi8(_end)\n"
" ldi r24,lo8(0xc5)\n" // STACK_CANARY = 0xc5
" ldi r25,hi8(__stack)\n"
" rjmp .cmp\n"
".loop:\n"
" st Z+,r24\n"
".cmp:\n"
" cpi r30,lo8(__stack)\n"
" cpc r31,r25\n"
" brlo .loop\n"
" breq .loop"::);
#endif
}

uint16_t mu_StackCount(void)
{
uint8_t *p = (__brkval == 0 ? (uint8_t *) &__heap_start : __brkval);

while (*p == STACK_CANARY && (int) p <= SP)
p++;

return (uint16_t)RAMEND - (uint16_t)p;
}
97 changes: 74 additions & 23 deletions MemoryUsage.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
MemoryUsage.h - MemoryUsage library
MemoryUsage.h - MemoryUsage library V2.0
Copyright (c) 2015 Thierry Paris. All right reserved.
This library is free software; you can redistribute it and/or
Expand All @@ -20,37 +20,88 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef __MemoryUsage_h__
#define __MemoryUsage_h__

// Must be used only one time, outside any function.
#define STACK_DECLARE byte *stack_end_max;
#include <stdint.h>

/*
Roughly, the SRAM memory is divided into four areas: the static data, the heap, the free ram and the stack.
The static data size is given by the compiler itself after the building. this is filled by all variables and
arrays declared in global scope, or with 'static' keyword.
The heap is filled with all the dynamic allocations done with 'new' keyword or 'malloc' functions.
The stack start from the end of the SRAM area and grow and shrink downward at each function call.
SRAM memory
+---------------+------------------+---------------------------------------------+-----------------+
| | | | |
| | | | |
| static | | | |
| data | heap | free ram | stack |
| | | | |
| | | | |
| | | | |
+---------------+------------------+---------------------------------------------+-----------------+
_end or __heap_start __brkval SP RAMEND
Source : http://www.nongnu.org/avr-libc/user-manual/malloc.html
*/

extern uint8_t _end;
extern uint8_t __stack;
extern uint8_t *__brkval;
extern uint8_t *__data_start;
extern uint8_t *__heap_start;

//
// Memory addresses
//

#define MEMORY_PRINT_START { Serial.print(F("Data start:")); Serial.println((int) &__data_start); }
#define MEMORY_PRINT_HEAPSTART { Serial.print(F("Heap start:")); Serial.println((int)&__heap_start); }
#define MEMORY_PRINT_HEAPEND { Serial.print(F("Heap end:")); Serial.println(__brkval == 0 ? (int)&__heap_start : (int)__brkval); }
#define MEMORY_PRINT_STACKSTART { Serial.print(F("Stack start:")); Serial.println((int) SP); }
#define MEMORY_PRINT_END { Serial.print(F("Stack end:")); Serial.println((int) RAMEND); }

#define MEMORY_PRINT_HEAPSIZE { Serial.print(F("Heap size:")); Serial.println((int) (__brkval == 0 ? (int)&__heap_start : (int)__brkval) - (int)&__heap_start); }
#define MEMORY_PRINT_STACKSIZE { Serial.print(F("Stack size:")); Serial.println((int) RAMEND - (int)SP); }

//
// Stack count part. STACK_COMPUTE will get the maximum size of the stack at the moment...
//

// Must be used inside a function, as soon as possible, basicaly at the beginning of the setup().
// Can be recalled at any time to reset the stack counter and have a local count of stack bytes.
#define STACK_START byte b_Stack; stack_end_max = &b_Stack;
// Must be used only one time, outside any function.
#define STACK_DECLARE unsigned int mu_stack_size = (RAMEND - SP);

// Must be call to update the current maximum size of the stack, at each function beginning.
#define STACK_COMPUTE { byte b_Stack; \
byte *stack_local_end = &b_Stack; \
if ((int) stack_local_end < (int) stack_end_max)\
stack_end_max = stack_local_end; }
// Must be called to update the current maximum size of the stack, at each function beginning.
#define STACK_COMPUTE { mu_stack_size = (RAMEND - SP) > mu_stack_size ? (RAMEND - SP) : mu_stack_size;}

// Compute the current maximum and show it now with customized text.
#define STACK_PRINT(text) { STACK_COMPUTE; Serial.print(text); Serial.println(RAMEND - (int) stack_end_max); }
#define STACK_PRINT_TEXT(text) { STACK_COMPUTE; Serial.print(text); Serial.println(mu_stack_size); }

// Compute the current maximum and show it now with default text.
#define STACK_PRINT STACK_PRINT(F("Stack Size:"));
#define STACK_PRINT STACK_PRINT_TEXT(F("Stack Maximum Size (Instrumentation method): "));

//
// Free Ram part.
//

// Shows the current free SRAM memory with customized text.
#define FREERAM_PRINT(text) Serial.print(text); Serial.println(freeRam());
#define FREERAM_PRINT_TEXT(text) Serial.print(text); Serial.println(mu_freeRam());

// Shows the current free SRAM memory with default text.
#define FREERAM_PRINT FREERAM_PRINT(F("Free Ram Size:"));

// Thanks to adafruit : https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory
int freeRam ()
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
#define FREERAM_PRINT FREERAM_PRINT_TEXT(F("Free Ram Size: "));

int mu_freeRam(void);

//
// StackPaint part. This macro gives a view of used stack area at the end of execution...
//

uint16_t mu_StackCount(void);

// Compute the current maximum and show it now with customized text.
#define STACKPAINT_PRINT_TEXT(text) { Serial.print(text); Serial.println(mu_StackCount()); }

// Compute the current maximum and show it now with default text.
#define STACKPAINT_PRINT STACKPAINT_PRINT_TEXT(F("Stack Maximum Size (Painting method): "));


#endif
31 changes: 30 additions & 1 deletion examples/FreeRam/FreeRam.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,43 @@
void setup()
{
Serial.begin(115200);
Serial.println(F("Starting state of the memory:"));
Serial.println();

MEMORY_PRINT_START
MEMORY_PRINT_HEAPSTART
MEMORY_PRINT_HEAPEND
MEMORY_PRINT_STACKSTART
MEMORY_PRINT_END
MEMORY_PRINT_HEAPSIZE

Serial.println();
Serial.println();

FREERAM_PRINT;

byte *p = new byte[3000];

Serial.println();
Serial.println();

Serial.println(F("Ending state of the memory:"));
Serial.println();

MEMORY_PRINT_START
MEMORY_PRINT_HEAPSTART
MEMORY_PRINT_HEAPEND
MEMORY_PRINT_STACKSTART
MEMORY_PRINT_END
MEMORY_PRINT_HEAPSIZE

Serial.println();
Serial.println();

FREERAM_PRINT;
}

void loop()
{

}
}
Loading

0 comments on commit edfc986

Please sign in to comment.