Hi, ich bin grad am suchen, wie ich einen Cortex M4 neu starten kann ohne den reset auszuführen. Es geht um einen LPC4330. Problem ist, dass bei einem normalen Reset der ROM Bootloader durchlaufen wird und das führt manchmal du einer Situation wo die CPU in einer Endlosschleife hängt bevor überhaupt mein Code ausgeführt wird. Ich will/muss aus einer beliebigen Stelle, auch zB aus dem harfault IRQ meinen code neu bei 0x00 starten. Das ist nicht so einfach, weil die CPU ja im Handler mode sein könnte und die Stackpointer resetet werden müssen. Weiss jemand wie ich im hardfault handler zurück in den Thread mode schalten kann und was ich sonst dabei beachten muss? Danke, Simon
Hi, Bin mir nicht sicher, ob wir das gleich meinen, aber ich es so gelöst in einer Applikation. Ergebnis ist ein Warm-Start ohne Power-Cycle. War allerdings ein M3 if (lpcImgInfo->prodID == 583) { spImage = (uint32_t*) 0x14020000; } else { spImage = (uint32_t*) 0x14010000; } NVIC_SetVTOR((uint32_t)spImage); __set_MSP(*spImage); /* Load stack pointer of the selected image */ __enable_irq(); // Call the first function in the Vector Table // (this is the reset vector at offset 0x4) bootAddr = spImage + 1; ((void (*)())(*bootAddr))(); // never get to here, diverted by boot while (1);
Hi, Super, das hilft mir mit dem stack pointer! ich vermute, du rufst das nie aus einem IRQ, geschweige denn fault IRQ auf, weil dann wäre die CPU nicht im thread mode und einige oder alle IRQs wären weithin geblockt. Hast du dazu eine Idee? danke, Simon
cfgardiner schrieb: > ((void (*)())(*bootAddr))(); Darum hasse ich C manchmal. Was ist denn das für ein Konstrukt?
*bootAddr zeigt auf eine Adresse, die main() Routine das ganze drum herum macht aus der Adresse einen Funktionszeiger und ruft den auf. Es ist somit der main(); Aufruf, bzw. der Einsprungpunkt in den ersten Befehl, der die CPU ausführt. Man könnte auch die Adresse *bootAddr in den PC (ProgrammCounter) schreiben, ist das gleiche.
Stimmt. Aus den Exceptions heraus hatte ich es anders gelöst. Das ist allerdings NXP spezifisch(aber das hast Du ja). Mit den aktuellen lpcopen 2.12 ist der Aufruf leider etwas anders, glaube ich (muesste ich noch suchen). Das unten stehende kann man aber auch einfach zu Fuss programmieren: Applikation =========== z.B. void BusFault_Handler(void) { RGU_SoftReset(RGU_SIG_CORE); } NXP hat RGU_SoftReset so definiert: =================================== typedef enum { RGU_SIG_CORE = 0, /**< Core reset signal */ RGU_SIG_PERIPH, /**< Peripheral reset signal */ RGU_SIG_MASTER, /**< Master reset signal */ . . . . . . . RGU_SIG_SPIFI, /**< SPIFI reset signal */ RGU_SIG_CAN = 55 /**< CAN reset signal */ }RGU_SIG; void RGU_SoftReset(RGU_SIG ResetSignal) { if(ResetSignal < 32){ LPC_RGU->RESET_CTRL0 = 1 << ResetSignal; LPC_RGU->RESET_CTRL0 = 0; }else{ LPC_RGU->RESET_CTRL1 = 1 << (ResetSignal - 32); LPC_RGU->RESET_CTRL1 = 0; } }
Habe ich doch gefunden. mit lpcopen heisst es void Chip_RGU_TriggerReset(CHIP_RGU_RST_T ResetNumber); ist aber das gleich in grün: lpcopen/software/lpc_core/lpc_chip/chip_18xx_43xx/rgu_18xx_43xx.c /* Trigger a peripheral reset for the selected peripheral */ void Chip_RGU_TriggerReset(CHIP_RGU_RST_T ResetNumber) { volatile uint32_t *p; /* To trigger reset- write RESET_CTRLx with a 1 bit */ p = (volatile uint32_t *) &(LPC_RGU->RESET_CTRL0); /* higher numbers are in RESET_CTRL1, RESET_CTRL2, etc. */ p += ResetNumber / 32; /* On the LPC18xx and LPC43xx, most of the reset bits automatically clear after 1 clock cycle, so set the bit and return */ *p = (1 << (ResetNumber % 32)); }
Hi, danke für die Mühe, aber das führt wieder dazu dass der ROM Bootloader durchlaufen wird :-) Problem ist, dass der dann den ISP pin prüft, und ggf in den ISP Mode wechselt. Dieser Pin ist gleichzeitig eine Adressleitung vom SDRAM. Und das SDRAM musste ich abschaltbar machen um Strom zu sparen. Es ist so verschaltet, dass der SDRAM mit Strom versorgt wird sobald die IOs in den reset-state gehen, aber offenbar ist das Timing nicht immer ausreichend. Ganz ganz selten wird dann doch der ISP aufgerufen... Hab das schon auf alle erdenkliche Arten versucht, Timing stimmt jetzt perfekt, trotzdem passierts manchmal. ==> deshalb würde ich den ROM Bootloader gerne nie durchlaufen, brauch ihn ja auch nicht. Ich hatte zwischenzeitlich noch eine Idee, aber noch nicht versucht. Evtl. würde es ja gehen, zuerst mit PRIMASK und BASEMASK alle IRQs zu deaktivieren. Dann alle pending löschen und nur den ResetISR pending setzen. Vector table auf den bootloader setzen. Dann Stack und evtl CONTROL passend setzen, und die IRQs wieder aktiveren. Fault Handler mit return verlassen. Dann müsste doch eigentlich der ResetHandler im bootloader angesprungen werden und alles müsste passen, oder? Naja, ich denk grad noch drüber nach... Grüße, Simon
Der STM32 hat ein Register in dem drin steht wer den Reset ausgelöst hat. Wenn man ein Soft-Reset über die Befehle macht springt der zwar in Bootloader, aber der kann dieses Register auslesen und so direkt zu Applikation springen. Das müsste es beim LPC auch geben.
:
Bearbeitet durch User
S. C. schrieb: > Es ist so verschaltet, dass der SDRAM mit Strom versorgt wird sobald die > IOs in den reset-state gehen, aber offenbar ist das Timing nicht immer > ausreichend. Evtl. bringt es was, hier noch einen hochohmigen Pullup/Pulldown unterzubringen, um geordnete Verhätlnisse zu schaffen.
Hast Du mal versucht, CRP auf "NO_ISP" zu setzen? Siehe Kapitel 6.6 im UM10503.pdf Manual. Dann sollte der Pegel auf P2.7 beim Reset egal sein.
Hi, - Register gibts, aber der ROM bootloader ist von NXP, den kann ich nicht beeinflussen - Pullup ist schon da, kann aber nur gegen die Versorgungsspannung vom SDRAM gehen, sonst würde er ja das ganze SDRAM versorgen wenn es abgeschaltet ist. Vor dem Reset setze ich auch mit Gewalt die Pegel, aber auch das hilft nicht 100%ig - CRP wäre eine super Idee, aber der 4330 hat kein Flash sondern bootet vom externen SPIFI. Laut Flußdiagram wird der ISP pin nur dann nicht abgefragt wenn die CPU AES kann und auch eine Key programmiert ist. Die CPU kann aber kein AES...blöde Konstellation. Danke, Simon
S. C. schrieb: > - Pullup ist schon da, kann aber nur gegen die Versorgungsspannung vom > SDRAM gehen, sonst würde er ja das ganze SDRAM versorgen wenn es > abgeschaltet ist. > Vor dem Reset setze ich auch mit Gewalt die Pegel, aber auch das hilft > nicht 100%ig wie wäre es an der stelle mit einem kleinen puffer zwischen µC und SDRAM? Z.B. so ein 74lvc2g17. Der erlaubt am Input 0-5V auch bei ausgeschalteter eigener Stromversorgung. Den 74lvc2g17 versorgst Du mit der selben Stromversorgung wie den SDRAM und erst wenn die angeht, gibt er einen Pegel aus. Damit kannst Du dann einen sauberen Pullup an die Stromversorgung des µCs realisieren.
:
Bearbeitet durch User
S. C. schrieb: > Ich will/muss aus einer beliebigen Stelle, auch zB aus dem harfault IRQ > meinen code neu bei 0x00 starten. > > Das ist nicht so einfach, weil die CPU ja im Handler mode sein könnte > und die Stackpointer resetet werden müssen. Genau dafür kann man doch 2 Stacks einrichten: R13_PSP für Thread und R13_MSP für Handler. The Stack Pointer (SP) is register R13. In Thread mode, bit[1] of the CONTROL register indicates the stack pointer to use: 0 = Main Stack Pointer (MSP). This is the reset value. 1 = Process Stack Pointer (PSP).
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.