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:
BEARBEITEN:
#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 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.
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.
and.w r4, r2, #0x1, add.w r4, r4, #0xFF00
EDIT : Entschuldigung, mein schlechtes (und & hinzufügen)
Dzarda
David Tweed
Scott Seidmann
Kaz
Benutzer3696425
Dzarda
Benutzer3696425