Stack address > 2k for ATMEGA328p?

I am using the Arduino Ethernet board.

I modified the BareMinimum.ino example sketch that comes with the memoryfree library to the following:

#include <MemoryFree.h>;

void setup() {
  Serial.begin(9600);
  Serial.print(F("Free RAM = "));
  Serial.println(freeMemory(), DEC);  
  Serial.print(F("Stack Address = "));
  int v;
  Serial.println((int)&v);
  Serial.print(F("Heap Address = "));
  extern int* __brkval;
  extern int __heap_start;
  Serial.println((int)__brkval);
  Serial.print(F("Heap Start = "));
  Serial.println((int)&__heap_start);

}

void loop() {

}

Can someone please help me understand the output I am getting?

Free RAM = 2287
Stack Address = 2292
Heap Address = 0
Heap Start = 455

How can the stack address be greater than 2048 for the atmega328p?

For fun i added the following:

  union {
    unsigned int all;
    struct{
      byte lo;
      byte hi;
    };
  } sp;   //bit shifting 8 times is against my religon
  
  sp.hi = SPH;
  sp.lo = SPL;
 
  Serial.print(F("Stack Pointer = "));
  Serial.println(sp.all);

Here is the output:

Free RAM = 2285
Stack Address = 2290
Heap Address = 0
Heap Start = 455
Stack Pointer = 2289

The first 256 bytes of address space are the 32 general registers and various I/O registers. SRAM starts at 256 decimal.

The stack starts at 2303 = 256 + 2047. The stack pointer is decremented when items are pushed.

Looks like freeMemory() has not been fixed for the latest change to malloc./heap. The Arduino company changed malloc() to a nonstandard version then changed it again. This broke lots of free memory programs twice.

Thanks for the response.

I was thrown off by the atmega328p datasheet diagram on page 18 (attached). The lower right shows the last address as 0x08FF. Just now I noticed the text:

The lower 768/1280/1280/2303 data memory locations address both the Register File, the I/O
memory, Extended I/O memory, and the internal data SRAM. The first 32 locations address the
Register File, the next 64 location the standard I/O memory, then 160 locations of Extended I/O
memory, and the next 512/1024/1024/2048 locations address the internal data SRAM.

Datasheet Page 18.png

fat16lib:
Looks like freeMemory() has not been fixed for the latest change to malloc./heap. The Arduino company changed malloc() to a nonstandard version then changed it again. This broke lots of free memory programs twice.

Here is my attempt at fixing it. Looks like it works to me.

#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
extern char __heap_start;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - &__heap_start;
#endif  // __arm__
}

Here is my new output (added a malloc to the code to test a non-zero heap):

Free RAM = 1821
Stack Address = 2288
Heap Address = 468
Heap Start = 461
Stack Pointer = 2286

Your "fix" looks a lot like my SdFat code from 5/4/2013. What do you claim is new?

04 May 2013

Fix FreeRam() for 1.05/1.53 malloc.

/* Arduino SdFat Library
 * Copyright (C) 2012 by William Greiman
 *
 * This file is part of the Arduino SdFat Library
 *
 * This Library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 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 General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with the Arduino SdFat Library.  If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <stdlib.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
extern char __bss_end;
#endif  // __arm__
//------------------------------------------------------------------------------
/** Amount of free RAM
 * \return The number of free bytes.
 */
int SdFatUtil::FreeRam() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#else  // __arm__
  return __brkval ? &top - __brkval : &top - &__bss_end;
#endif  // __arm__
}

freeMemory returns free memory for both the heap and stack. My (not likely your) FreeRam() only returns free memory for the stack.

fat16lib:
Your "fix" looks a lot like my SdFat code from 5/4/2013. What do you claim is new?

I dont think i understand your question or your point. All I did was take the a MemoryFree library that I downloaded off the Arduino website and edit it until it worked for me. I only posted this in case someone else is having similar trouble.

fat16lib:
freeMemory returns free memory for both the heap and stack.

I think you are saying that freeMemory() returns the free space taking into account both the stack and the heap. If I am understanding you correctly then I completely agree.

fat16lib:
My (not likely your) FreeRam() only returns free memory for the stack.

I dont see any functional difference in our code given that for Arduino __bss_end is the same as __heap_start:

I dont think i am understanding your point. If I made a mistake please let me know; I am here to learn.

All I did was take the a MemoryFree library that I downloaded off the Arduino website and edit it until it worked for me.

You lifted the SdFat code. You would never have put this in.

// should use uinstd.h to define sbrk but Due causes a conflict

Why are you claiming you wrote your "fix"?

fat16lib:

All I did was take the a MemoryFree library that I downloaded off the Arduino website and edit it until it worked for me.

You lifted the SdFat code. You would never have put this in.

// should use uinstd.h to define sbrk but Due causes a conflict

Why are you claiming you wrote your "fix"?

Now I see the point you are trying to make. I didn't at all intend to take credit for the fixed code. Sorry for my imprecise language.

I'm 90% sure the line you quoted was already in the MemoryFree library. That being said, I very well could have copied other parts (i dont remember).

Now i really wish i had kept a copy of the original code

Now i really wish i had kept a copy of the original code

Give it up. I wrote that code. It was first posted in SdFat in May 2013.

If you did download it where is it located? I would like to know who first lifted it. Did they remove the gnu licence?

My code:

#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
extern char __bss_end;
#endif  // __arm__
//------------------------------------------------------------------------------
/** Amount of free RAM
 * \return The number of free bytes.
 */
int SdFatUtil::FreeRam() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#else  // __arm__
  return __brkval ? &top - __brkval : &top - &__bss_end;
#endif  // __arm__
}

Your code:

#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
extern char __heap_start;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - &__heap_start;
#endif  // __arm__
}

Looks like mpflaga Arduino-MemoryFree/MemoryFree.cpp at master · mpflaga/Arduino-MemoryFree · GitHub lifted it from an old version of SdFat.

I fixed it about a year ago.

Here is the real freeMemory Arduino Playground - AvailableMemory

freeMemory() in this library gives stack and heap memory.

I glad you resolved the original highjack.

I have no doubt you are the original author and I sincerely thank your for your contribution. The last thing i want to do is piss off helpful forum folks such as yourself.