Wie findet man beim Zero den freien RAM heraus?

Moin zusammen!

Ich habe ein Problem auf dem Arduino Zero, das nach einem Überschreiben des Stacks aussieht. Dazu wüsste ich gerne, wie viel freier RAM noch verfügbar ist. Die im Netz verfügbare freeRam()-Funktion funktioniert auf dem Zero nicht, weil da die Symbole __brkval und __heap_start nicht bekannt sind.

Gibt es eine entsprechende Funktion, die auf dem Zero nutzbar ist?

Hallo,

wenn es da noch nichts gibt, dann müßtest du dir die Mühe machen, den neuen Namen für die Symbole/Adressen aus dem Datenblatt herauszufinden. Ich würde das Datenblatt vom Atmel 328P nehmen, nach den Namen suchen, verstehen wollen was das ist, wo die liegen und was die machen. Danach würde ich die gleiche Funktionalität beim Zero µC im Datenblatt suchen. Könnte klappen.

Selbst wenn das klappt, wäre das noch keine sichere Antwort. Weil man damit nur den statischen freien RAM herausbekommt. Du wirst bestimmt viel dynamischen RAM belegen. Für dynamischen muß man an allen erdenklichen Stellen im Programm die Stackbelegung abfragen.

Nur hat ein Zero eine Menge RAM. Wie bekommst du den gefüllt? Zeig mal den Code.

heap_start u.ä. sind keine Sachen, die direkt aus dem Hardware-Datenblatt kommen.
Wenn schon, müsstest du tief in der avr-gcc Umgebung speziell für 32bit arm-Prozessoren tauchen.

Das Zero Unterforum hier scheint in der Richtung mehr offene Fragen als Lösungen zu bieten :frowning:

Danke für Eure Antworten bisher. Den Code zu zeigen ist etwas problematisch, weil ich ein proprietäres SDK von Impinj (RFID-Reader) benutze, das bisher noch nicht auf den Arduino portiert wurde, allerdings schon auf andere Microcontroller (MSP430 z.B.). Der SDK-Code ist nicht öffentlich, leider.

Grundprinzip ist folgendes:

  • Starten eines "inventory"-Prozesses auf dem RFID-Reader, der nach Chips in der Umgebung scannt
  • Wird eines gefunden, wird aus dem SDK eine Callbackfunktion aufgerufen, die man vorher registrieren muss, und die das Scanergebnis in einem Puffer übergeben bekommt
  • Der Callback durchläuft selber mehrere Funktionen, der Puffer wird immer als Pointer weitergegeben

Ich komme immer eine kleine Anzahl von Callbacks weiter, bevor sich das Ding aufhängt, wie viele, scheint unbestimmt zu sein.

michael_x:
heap_start u.ä. sind keine Sachen, die direkt aus dem Hardware-Datenblatt kommen.
Wenn schon, müsstest du tief in der avr-gcc Umgebung speziell für 32bit arm-Prozessoren tauchen.

aha. :slight_smile:

@ Miq1
tja dann bist du in der Klemme. Frage im verlinkten Zero Teil nach. Vielleicht kann dir jemand helfen.
Ohne Code können wir nicht helfen. Nur raten. Das bringt nichts. Außer das vielleicht mit der Zeigerübergabe/rückgabe etwas nicht stimmt und der im Nirwana landet.
Wünsche maximale Erfolge.

Ein Post im Zero-Subforum brachte ein Ergebnis: GitHub - mpflaga/Arduino-MemoryFree: basic functions and example to use show used RAM and use less of it. funktioniert auch auf dem Zero! Die Lib definiert eine Funktion freeMemory(), die genau das macht, was ich brauche.

Leider bringt mich das nur ein Stückchen weiter... Der Speicher bleibt konstant, so lange der Sketch normal läuft. Dann tritt irgendeine mir noch nicht bekannte Nebenbedingung ein und der Stack wächst in 1KB-Schritten, bis die Kiste abschmiert.

Trotzdem allseits Danke! :wink:

Hast Du ungeplant irgendwie eine Rekursion ohne Abbruchbedingung geschaffen?

Gruß Tommy

Tja, nicht sichtbar für mich. Meine Seite des Codes läuft ja in den “guten” Inventory-Intervallen genauso wie beim Absturz. Ich habe mal ein Serial.println() an den Anfang und das Ende jeder meiner Funktionen gesetzt und das sieht auch ganz manierlich aus - bis plötzlich die Einstiegsmeldung in eine eher schlichte Funktion in schneller Folge ohne die Aufrufstruktur darüber erscheint, und jedesmal der RAM um 1KB geringer ist:

API Version: 010604F0 <== printed at the beginning of the run.
Inventory started
receive
receive
receive
receive
receive
receive
Report handler entry
tag operation handler entry
EPC = FF FF 05 42 20 00 00 00 00 00 00 00
Report handler entry
tag operation handler entry
EPC = FF FF 05 42 20 00 00 00 00 00 00 00
receive trailing
receive trailing
receive trailing
receive trailing
receive trailing
receive trailing
Inventory stopped
Report handler entry <========== Here we die…
Report handler entry
Report handler entry
Report handler entry
Report handler entry

Die Folge sollte sein: Inventory->receive->Report handler->tag operation handler. Der Report handler ist der, der vom Impinj-SDK aufgerufen wird, allerdings ist der eigentlich nicht ohne weitere Ausgabe zu verlassen, weil beide aufgerufenen Unterfunktionen gleich am Anfang eine Ausgabe haben (hier die neuere Version mit der Ausgabe des freien RAM):

ipj_error my_report_handler(ipj_iri_device *i, ipj_report_id report_id, void * report)
{
  ipj_error e = E_IPJ_ERROR_SUCCESS;
  Serial.print("Report handler entry. RAM=");
  Serial.println(freeMemory());
  switch (report_id)
  {
  case E_IPJ_REPORT_ID_TAG_OPERATION_REPORT:
    e = ipj_my_tag_operation_report_handler((ipj_tag_operation_report*)report);
    break;
  case E_IPJ_REPORT_ID_STOP_REPORT:
    e = ipj_my_stop_report_handler((ipj_stop_report*)report);
    break;
  default:
    Serial.print("REPORT ID NOT HANDLED: ");
    Serial.println(report_id);
    return E_IPJ_ERROR_GENERAL_ERROR;
    break;
  }
  return e;
}


ipj_error ipj_my_tag_operation_report_handler(ipj_tag_operation_report* tag_operation_report)
{
  Serial.println("tag operation handler entry");
  if (tag_operation_report->tag.has_epc)
  {
    Serial.print("EPC = ");
    ipj_my_print_epc((uint8_t*)tag_operation_report->tag.epc.bytes, (int)tag_operation_report->tag.epc.size);
  }
  if (tag_operation_report->tag.has_tid)
  {
    Serial.print("TID = ");
    ipj_my_print_epc((uint8_t*)tag_operation_report->tag.tid.bytes, (int)tag_operation_report->tag.tid.size);
  }
  return E_IPJ_ERROR_SUCCESS;
}

ipj_error ipj_my_stop_report_handler(ipj_stop_report* ipj_stop_report)
{
  Serial.println("STOP handler called");
  ipj_stopped_flag = 1;
  my_ipj.stop(E_IPJ_ACTION_INVENTORY);

  return E_IPJ_ERROR_SUCCESS;
}

Für/gegen Rekursion fallen mir ein:

Was bedeutet denn der Rückgabewert der Handler? Vielleicht sollte der auf E_IPJ_ERROR_SUCCESS gesetzt werden?

Vielleicht muß irgendein Wert in einer der Datenstrukturen auf "handled" gesetzt werden, um Rekursion zu beenden?

Die Bibliothek könnte fehlerhaft sein.