Куда девается столько памяти?

Arduino Uno, ATMEGA328P
Пока пытаюсь реализовать навигацию по файловой системе SD-карты.
Вот скетч, без ассемблерной части.

#define K_UP 5
#define K_DOWN 3
#define K_ENTER 6
byte OledTxtBuff[5][23];  // Текстовый буфер дисплея 4*21 с лишней строкой (для организации в будущем плавного скроллинга) и дополнительными 2 байтами на строку
byte shift=0;    
byte CursorX,CursorY;    
int  keyDown;
byte keyUp;
byte KeyPressed=0;
char FName[13];

const PROGMEM char inits1[]="Initializing SD card.";
const PROGMEM char inits2[]="initialization failed";
const PROGMEM char inits3[]="initialization done.";
const PROGMEM char NoFiles[]="No Files!!!";
const PROGMEM char Updir[]="[..]";

#include <SPI.h>
#include <SD.h>
File Dir,entry; // для экономии памяти эту хрень сделаем глобальной

extern "C" {
 void OledInitialize();
 void TxtRefresh();
 void Pause(byte p);
}

void setup() {
  OledInitialize();
  pinMode(A1,INPUT_PULLUP);
  pinMode(A2,INPUT_PULLUP);
  pinMode(A3,INPUT_PULLUP);
  CursorX=0; CursorY=1;
  Serial.begin(9600);
  StringOut(inits1);
  if (!SD.begin(4)) {
    CursorX=0;
    CursorY=2;
    StringOut(inits2);
    while (1);
  }
  CursorX=0; CursorY=2;
  StringOut(inits3); 
}

void loop() 
{
  WaitKeyPress();
  Dir=SD.open("/");
  DirView("/",1); 
}


// level=1 для корня, =0 для подпапок
void DirView(char * sroot, byte level)
{
  Serial.print("after ");Serial.println(getRamFree());
  int Selected=level;
  byte Fpos=0;
  // Вычисляем кол-во файлов в папке
  int FCnt=0;  
  while (true)  {  
    entry =  Dir.openNextFile(); 
    if (!entry) {break;} 
    FCnt++;
    entry.close();
  }
  // если в корне нет ничего
  if ((level==1) and (FCnt==0)) 
  {
    CursorX=0;
    CursorY=5;
    ClearBuffer();
    StringOut(NoFiles);
    while(1);
  }
  while (true)
  {
    // отрисовка фрагмента списка файлов
    ClearBuffer();
    Dir.rewindDirectory();
    for (int k=1;k<Selected-Fpos;k++){Dir.openNextFile().close();};
    for (CursorY=0; CursorY<4;CursorY++) 
    { 
      if (CursorY==Fpos)  {OledTxtBuff[CursorY][3]=0x3D; OledTxtBuff[CursorY][4]=0x3E; } // рисуем стрелочку => для выбора
      CursorX=5;      
      if ((Selected+CursorY-Fpos)==0) {TStringOut(Updir); continue;}
      if (Selected+CursorY-Fpos>FCnt) {break;}
      entry=Dir.openNextFile();
      if (entry.isDirectory()) {TStringOut(entry.name());} else { strcpy(FName,entry.name()); DownCase(FName); TStringOut(FName);};
      entry.close();
    }
    TxtRefresh();
    // обработка навигации
    WaitKeyPress();
    if ((KeyPressed==K_UP) and (Selected>level)) {Selected--; if (Fpos>0) {Fpos--;}}
    if ((KeyPressed==K_DOWN) and (Selected<FCnt)) {Selected++; if (Fpos<3) {Fpos++;}}
    if (KeyPressed==K_ENTER) 
    {
      if (Selected==0) 
      {
        Dir.close(); return;  // Возврат на предыдущий уровень
      } else {
        Dir.rewindDirectory();
        for (int k=1;k<Selected;k++){Dir.openNextFile().close();}
        entry=Dir.openNextFile(); 
        if (entry.isDirectory()) 
        { 
          // Готовимся к переходу на следующий уровень
          Dir.close(); // Закрываем для экономии памяти. Путь к родительскому каталогу занимает меньше памяти. Из него и восстановим.
          Dir=entry;        
          // Готовим путь для возврата. Пока он готовится на 1 шаг вперед, что явно лишнее. Нужно подумать и переделать.
          char subroot[strlen(sroot)+strlen(Dir.name())+2];
          strcpy(subroot,sroot);
          strcat(subroot,Dir.name());
          strcat(subroot,"/");
          Serial.println(subroot);
          Serial.print("before ");Serial.println(getRamFree());
          DirView(subroot,0);   // На следующий уровень вложенности
          Dir=SD.open(sroot);   // Возврат из подкаталога. Восстанавливаем подкаталог по его пути.
        } else {
          // Выбран файл, то нужно его обработать, пока не реализовано
          entry.close();    
        }
      }
    }
  } 
}

void WaitKeyPress(void) {
  KeyPressed=0;
  while (KeyPressed==0) {KeyPressed=KeyPress();}
}

byte KeyPress(void) {
  byte res=0;
  byte KEY=((digitalRead(A3)<<2)|(digitalRead(A2)<<1)|digitalRead(A1))&7;
  if ((KEY==K_UP) or (KEY==K_DOWN) or (KEY==K_ENTER)) {keyDown++; res=(keyDown==1&&keyUp==200 ? (KEY) :0); keyUp=0;} else {keyDown=0; keyUp++;}
  if (keyDown>=15020) {keyDown=15000; res=KEY;}
  if (keyUp>=200) {keyUp=200;}
  Pause(0);
  return res;
}

void StringOut(char *S) {
   for (byte i=0;i<strlen(S);i++)  {OledTxtBuff[CursorY][CursorX+i]=S[i];}
    TxtRefresh();
}

void TStringOut(char *S) {
   for (byte i=0;i<strlen(S);i++)  {OledTxtBuff[CursorY][CursorX+i]=S[i];}
}

void StringOut(const char *S) {
    for (byte i=0;i<strlen_P(S);i++) {OledTxtBuff[CursorY][CursorX+i]=pgm_read_byte(S+i);}
    TxtRefresh();
}

void TStringOut(const char *S) {
    for (byte i=0;i<strlen_P(S);i++) {OledTxtBuff[CursorY][CursorX+i]=pgm_read_byte(S+i);}
}

void DownCase(char * S){
  for (byte i=0;i<strlen(S);i++) { if ((S[i]>0x3F) and (S[i]<0x60)) {S[i]=S[i]+0x20;}}
}

void ClearBuffer(void) {
  for (byte i=0;i<5;i++) {
    for (byte j=0;j<23;j++) {
      OledTxtBuff[i][j]=0;
    }
  }
}

inline uint32_t getRamFree(void) {
  extern uint16_t __heap_start, *__brkval;
  uint16_t v;
  return (uint32_t) &v - (__brkval == 0 ? (uint32_t) &__heap_start : (uint32_t) __brkval);
}

Замеряю кол-во свободной памяти до вызова функции и сразу же после вызова
При переходе на несколько уровней вложенности каталогов в СОМ порту получаю следующее:

after 891
/KATEG1/
before 860
after 790
/KATEG1/SUB2/
before 821
after 746
/KATEG1/SUB2/HHHH/
before 715
after 635

Видно, что при очередном вызове функции тратится от 70 до 80 байт
Куда может столько тратиться, если там нужно в стеке сохранять максимум 34 байта (32 регистра и адрес возврата)? Локальных переменных там мало, для них регистров более чем достаточно. В куче по идее должна размещаться единственная переменная subroot, но она создается между after и before, а в данном случае меня интересует что творится между before и after.
т.е. между этим:

...
          Serial.print("before ");Serial.println(getRamFree());
          DirView(subroot,0);   // На следующий уровень вложенности
...

и этим:

void DirView(char * sroot, byte level)
{
  Serial.print("after ");Serial.println(getRamFree());
...

Куда программа может расходовать столько памяти?

Ну, например, только на строке "before " она теряет 8 байт, а на строке "after " - еще 7.

Ну before тут не причем. Память замеряется после него. Что касается after, то разве выделенная под него память к моменту Serial.println(getRamFree()) не должна была освободиться? Но даже если она и не освобождается, все равно 7 байт - слишком мало , чтобы объяснить такую разницу.

Убрал Serial.print("after ");
в COM выводится:

897
/KATEG1/
before 866
796

Т.е. все равно получаю тех же 70 байт (866-796), так что after тоже тут не причем.