Winziger Code zum Dumping des Flash-Speichers

Ich versuche, so wenig Code wie möglich zu schreiben, um die Firmware des Mikrocontrollers XMC4500 von Infineon zu extrahieren .

Der Code muss in einen 30- Byte-Puffer passen , der es mir ermöglicht, 15 Maschinenbefehle mit dem 16-Bit-Befehlssatz von Thumb zu haben.

Beginnend mit C ist mein Versuch, Flash-Speicher über einen einzelnen GPIO-Pin (siehe ursprüngliche Frage) nach diesem raffinierten Trick zu entleeren.

Grundsätzlich mache ich folgendes:

  1. Richten Sie die GPIO-Pin-Richtungen für die Ausgabe ein
  2. LED1 (Pin 1.1) mit einer Uhr blinken (serielle SPI-Uhr)
  3. Blink LED2 (Pin 1.0) mit Datenbits (SPI MOSI)
  4. Pins mit einem Logikanalysator schnüffeln

BEARBEITEN:

  1. C-CODEBLOCK AKTUALISIEREN
  2. MONTAGECODEBLOCK HINZUFÜGEN
#include "XMC4500.h"

void main() {
  // start dumping at memory address 0x00000000
  unsigned int* p = (uint32_t *)(0x0u);

  // configure port1 output (push-pull)
  PORT1->IOCR0 = 0x8080u;

  for(;;) {
    int i = 32;

    int data = *(p++);

    do {
      // clock low
      PORT1->OUT = 0x0;

      // clock high with data bits
      PORT1->OUT = 0x2u | data;

      data >>= 1;

    } while (--i > 0);
  }
}
main:
    ; PORT1->IOCR0 = 0x8080UL
    ldr r1, =0x48028100 ; load port1 base address to R1
    movw r2, #0x8080 ; move 0x8080 to R2
    str r2, [r1, #0x10]

main_1:
    ; start copying at address 0x00000000
    ; R12 is known to be zeroed
    ldr.w r2, [r12], #0x4 ; int data = *(p++)
    movs r3, #32 ; int i = 32

main_2:
    ; PORT1->OUT = 0x0
    ; clock low
    ; R12 is known to be zeroed
    str r12, [r1]

    ; PORT1->OUT = 0x2 | data
    ; clock high with data bits
    orr r4, r2, #0x2
    str r4, [r1]

    asrs r2, r2, #0x1 ; data >>= 1

    subs r3, r3, #0x1 ; i--
    bne.n main_2 ; while (--i > 0)
    b.n main_1 ; while(true)

Die Codegröße ist jedoch immer noch zu groß, um meine Anforderungen zu erfüllen.

Kann ich irgendetwas tun, um meinen Code weiter zu verkleinern? Gibt es etwas, das optimiert oder weggelassen werden kann?

Ich glaube nicht, dass dies realistisch möglich ist, aber ich werde versuchen, es zu beantworten. Edit: Könnten Sie posten, was der Assembler daraus gemacht hat?
Obwohl es nützlich sein kann, darüber konzeptionell in C zu sprechen, müssen Sie die endgültige Optimierung mit ziemlicher Sicherheit direkt im Assembler-Code vornehmen.
Sie haben dort viele Verzweigungen, die Sie anscheinend nicht brauchen. "Wenn das Bit eins ist, senden Sie eins, und wenn es null ist, senden Sie null" scheint, als sollten Sie in der Lage sein, es zu rationalisieren.
Wenn alles andere fehlschlägt, versuchen Sie selbstmodifizierende Codetricks.
@Dzarda Bitte finden Sie die generierte Assembly oben.
@ user3696425 Also, was ist die Codegröße an dieser Stelle?
@Dzarda Entschuldigung, vergessen zu erwähnen: Es sind jetzt 44 Bytes.

Antworten (2)

Ich bin es nicht gewohnt, für ARM-Prozessoren zu programmieren und weiß nicht, welchen Compiler Sie verwenden, also bringen die vorgeschlagenen Änderungen vielleicht überhaupt nichts, aber hey, versuchen wir es zumindest!

1-Integrieren Sie Ihre Funktionen:

Ein guter Compiler sollte eine Funktion bereits einbetten, wenn die Optimierungen gut eingestellt sind, aber es lohnt sich, sie einzubetten, damit Sie die Aufrufe und Rets entfernen

2-Verzweigungen vermeiden:

In einigen Architekturen kann ein IF übersetzt werden in: Laden, Testen, Verzweigen, drei Anweisungen, wenn Sie es ohne Verzweigen tun können, können weniger Anweisungen verwendet werden.

Der vorgeschlagene Code lautet also:

    int main() 
    {
      // start dumping at memory address 0x08000000
      unsigned int *p;
      int i;

      p = (uint32_t *)(0x08000000u);

      // configure pin 1.0 and pin 1.1 as output (push-pull)
      PORT1->IOCR0 = 0x8080UL;

      do
      {
        for (i = 0; i < 32; i++)
        {
          // set pin 1.1 to low (SPI clock)
          PORT1->OUT &= (~0x2UL);
          PORT1->OUT = (PORT1->OUT & 0xFFFE) | (data & 0x01)
          PORT1->OUT |= 0x2UL;
          data >>= 1;
        }

      }while(p++)
    }

Probieren Sie es aus und kommentieren Sie die Ergebnisse.

Guter Ausgangspunkt! Es gelang, die Codegröße auf 44 Byte zu verkleinern. Jetzt muss ich in die generierte Assembly eintauchen (siehe Codeblock oben), um die Codegröße noch weiter zu verbessern.

Dies setzt voraus, dass Ihr 32-Byte-Programm der einzige auf dem Chip verfügbare Code ist. Es sind keine externen Anrufe erlaubt.


Eine Sorge bei Ihrem C-Code wäre die Einbeziehung und Verwendung des Headers "XMC4500.h". Auch wenn Sie nur die "PORT1" -Struktur verwenden, damit der Rest optimiert wird / wird, denke ich immer noch, dass Sie einen effizienteren GPIO-Registerzugriff erhalten können.

Zweitens nehme ich an, dass Sie aufgrund Ihres Fehlens von Informationen über die "Projekteinstellungen" keine Schritte unternommen haben, um Ihren Linker zu zwingen, Ihren Code an eine bestimmte Stelle zu quetschen, die Interrupt-Tabelle, den Initialisierungscode usw. wegzulassen. Vielleicht möchten Sie hier einen Blick darauf werfen . Grundsätzlich heißt es, dass Sie durch Ändern der .ld/.lds-Dateien den Linker zwingen können, bestimmte Codeabschnitte an bestimmten Adressen zu platzieren.
Ein solches Skript könnte wie folgt aussehen:

SECTIONS {
        . = YOUR_DESIRED_ADDRESS; 
        .text : { * (.text); }
}

Ich werde die Antwort bearbeiten, sobald neue Ideen kommen.

1. Mein Programm ist der einzige Code auf dem Chip. 2. Mir geht es gut mit meiner Header-Datei, kein Grund zur Sorge. 3. Das Zusammenführen und Platzieren von Abschnitten ist ebenfalls in Ordnung.
Nur ein zufälliger Gedanke, warum nicht diese beiden Adds zusammenführen? and.w r4, r2, #0x1, add.w r4, r4, #0xFF00 EDIT : Entschuldigung, mein schlechtes (und & hinzufügen)
Tut mir leid, Kumpel, das erfordert einen ARM-Montage-Guru, nicht mich. Aber ich vermute, Sie können vielleicht 2 oder 4 Bytes abschneiden, Sie passen nicht zu 32 Bytes ...
Kein Problem. Die Codegröße wurde auf 36 Byte optimiert (siehe aktualisierte Codeblöcke oben). Noch drei Anweisungen (6 Bytes) und mir geht es gut :-)