2017-12-01 6 views
2

Ich arbeite an einer Reihe von Debugging-Tools für einige interne Cortex-M4-Kerne. Ich erstelle eingebettete (keine OS) ELF Bilder mit einer gcc/binutils Toolchain und simuliere sie mit einer modifizierten Version von QEMU. Ich erstelle die Interrupt-Vektortabellen am Anfang (d. H. 0) meiner Bilder und initialisiere den Stapelzeiger und die Startadresse (d. H. Die Adresse der Hauptadresse) korrekt.Soft-Reset auf einem Cortex-M mit GDB

Die Zielprogramme werden wie erwartet ausgeführt und die Debug-Tools, die unter Verwendung des entfernten GDB-Protokolls erstellt wurden, funktionieren ordnungsgemäß.

Was ich gerade versuche zu verstehen ist, wie man einen Soft-Reset von GDB initiiert. Das heißt, veranlassen, dass das Zielprogramm neu initialisiert wird, wobei der Stapelzeiger auf den Anfangswert in der Vektortabelle zurückgesetzt wird, und der PC zurück an der Startadresse.

Ich habe mir bereits gezeigt, dass die Aktion des Festlegens des PC-Werts auf 0 und das Ausführen des Kerns nicht geeignet ist, und das Ergebnis war, dass mein "UsageFault" -Ausnahmehandler aufgerufen wurde. (Ich gehe davon aus, dass der Kern im falschen Modus ist, um diese Art von Aktion auszuführen).

Gibt es eine Technik, d. H. Durch Register schreibt mit GDB Remote-Protokoll, dass ich den simulierten Kern soft-reset kann, das heißt, ohne die QEMU-Sitzung aus- und wieder einschalten zu müssen?

+0

Adresse 0 ist der anfängliche Stapelzeiger. –

+0

Korrigieren. Direkter Zugriff auf den SP aus einer Anwendung wird jedoch von Cortex-M im Thumb-Modus verhindert. Da die Neuinitialisierung des SP eine Anforderung eines SW-Reset ist, ist eine andere Methode erforderlich. Viks Antwort unten scheint nahe bei dem zu sein, was benötigt wird, ich muss nur genau debuggen, was eigentlich ist, wenn ich QEMU den Speicher über GDB schreibe. –

Antwort

0

können Sie machen SW Neustart von SYSRESETREQ Bit + KEY in AIRCR Register schreibt:

AIRCR_REG_ADDRESS = 0xe000ed0c 
AIRCR_KEY = 0x05fa0000 
AIRCR_SYSRESETREQ_BIT = 0x00000004 

AIRCR_REG = AIRCR_KEY | AIRCR_SYSRESETREQ_BIT 

Mehr Informationen ist here

Dies ist mit allen Cortex-M arbeitet

+0

Ich probiere deinen Vorschlag aus. QEMU verarbeitet das Schreibpaket, aber ich bin mir nicht sicher, ob die richtige Aktion ausgeführt wird. –

+0

Das sieht nach einer vernünftigen Lösung aus, aber derzeit scheint es, dass die QEMU-Instanz, die ich verwende, um eine echte CPU zu simulieren, den erforderlichen Bereich (den SCB) nicht korrekt emuliert. –

+0

Ok, in diesem Fall benutze vor der Einstellung 'AIRCR' auch [' DEMCR'] (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/CEGHJDCF.html) registriere und setze das Bit 'VC_CORERESET' (' DEMCR = 0x00000001'), diese halt CPU nach dem Reset und du kannst in SP, PC, ... nachsehen, ob es korrekt neugestartet wurde – vlk

0

Dies ist ein Ausschnitt Code für einen Cortex-M3 Ich spring zu jeder Stelle mit gültigem Code (einschließlich Springen zu 0):

IRQn_Type interrupt = (IRQn_Type)0; 
    app_fn jump = *(app_fn *)(jumpaddr + sizeof(int));  //Reset is 2nd in table 
    uint32_t stack_adr = *(uint32_t *)(jumpaddr);   //Stack pointer is 1st in table 

    //Disable interrupts before jumping 
    SysTick->CTRL &= ~ST_CTRL_ENABLE; 

    while (interrupt <= CANActivity_IRQn) 
    { 
     NVIC_DisableIRQ(interrupt); 
     interrupt++; 
    } 

    //Set the new stack pointer 
    __set_MSP(stack_adr); 

    //Set the new vector address 
    SCB->VTOR = (location & 0x1FFFFF80); 

    //Leap of faith! 
    jump(); 

Bei diesem Code wird davon ausgegangen, dass jumpaddr die Basisadresse einer Vektortabelle ist, da der Stapelzeiger an erster Stelle in der Tabelle steht und der Zurücksetzungshandler an zweiter Stelle in der Tabelle steht.

Das Deaktivieren von Interrupts ist ein Muss, da ein Interrupt ausgelöst werden kann, nachdem Sie den Stapelzeiger verschoben haben, der normalerweise eine Ausnahme verursacht.

Natürlich werden auf diese Weise keine Peripheriegeräte zurückgesetzt, so dass dies vor dem erneuten Aktivieren der Interrupts durchgeführt werden müsste.

Edit:

Sie können den Inhalt von __set_MSP finden here.

+0

Ich schaute nach __set_MSP. Wie schreibe ich diesen Code in GCC/Gas für ARM? Ich bin gespannt, wie funktioniert die Codeausführung ab Adresse 0, arbeite nach dem Sprung - ich hatte angenommen, dass der Prozessor zuerst einen Moduswechsel braucht? –

+0

Nicht ganz sicher, wie man es in gcc schreibt, aber könnte etwas wie sein: 'asm flüchtig (" msr msp,% 0 ":" = m "(stack_adr));' – NeRa

+0

Der obige Code wird im privilegierten Modus ausgeführt (kein Betriebssystem) von einem Bootloader. Ich verwende [NVIC_SystemReset] (https://github.com/ARM-software/CMSIS/blob/master/CMSIS/Include/core_cm3.h), um auf den Bootloader (bei 0x00000000) zurückzusetzen. – NeRa