Hallo alle zusammen... seit einer gefühlten Ewigkeit nun schon versuche ich verzweifelt auf einem LPC1549(Cortex M3 von NXP) FreeRTOS zum laufen zu bringen - Es will einfach nicht funktionieren: Dazu einiges zu meinen Fehlern: Ich verlang ja noch garnicht viel: in meiner main() steht irgendwann der Befehl "vTaskStartScheduler" was eigentlich dazu führen sollte das der Scheduler einen Idle-TAsk erstellt der damit beschäftigt ist, "idle" zu sein. Wenn ich "vTaskStartScheduler" in der main stehen habe, dann springt mein programmzeiger sofort in den hard_fault_handler ohne überhaupt die funktion zu erreichen. Wenn ichs dann mal auskommentiere funktioniert alles ganz normal: in der main() gehts los und da endet er dann irgendwann in einer while(1) schleife... Ich bin mir ziemlich sicher das die ganze Sache ihren Ursprung in der Priorityverteilung in der FreeRTOSCOnfig.h hat. Ehrlich gesagt habe ich auch nicht ganz gerafft: so wie ich das verstanden hab ist es bei einem cortex prozessor immer gut wenn man in der eben genannten Config für configKERNEL_INTERRUPT_PRIORITY den Wert 255 angibt, also die niedrigste priorität. Aber was genau bitte gebe ich jetzt configMAX_SYSCALL_INTERRUPT_PRIORITY an??? Wie kommt der Kernel überhaupt zum SYSTICK Handler und durch welche Bedingungen wird eigtl der Hard_FAULT_HANDLER ausgelöst? Welche Interrupts benutzt der Kernel überhaupt? Ich weiß irgendwie nicht weiter... Hier auf Arbeit konnte mir bisher auch keiner Helfen ich bin dankbar für jede noch so kleine hilfe...
Du musst schauen, dass im Startup file der Handler für den SV call auch korrekt die Funktion im RTOS aufruft, und nicht ein standard Handler aufgerufen wird.
meinst du die startup file von lpcExpresso? also in meinem fall die cr_startup_lpc15xx.c? Also die Handler sind ja da alle definiert... du sagst DIE rtos funktion... welche denn? Sry wenn ich ein bisschen langsam bin...
irgendwo steht sowas wie: __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler Anstatt SVC_Handler und PendSV_Handler muss aber irgendwas wie "RTOS_SVC..." stehen, falls es nicht schon so ist bei dir
Special note to ARM Cortex-M users: ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M4F ports need FreeRTOS handlers to be installed on the SysTick, PendSV and SVCCall interrupt vectors. The vector table can be populated directly with the FreeRTOS defined xPortSysTickHandler(), xPortPendSVHandler() and vPortSVCHandler() functions respectively, or, if the interrupt vector table is CMSIS compliant, the following three lines can be added to FreeRTOSConfig.h to map the FreeRTOS function names to their CMSIS equivalents: #define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler #define xPortSysTickHandler SysTick_Handler
Das hatte ich ja auch schon mal probiert, also das mit den #defines.. geht immernoch nicht! Obwohl ich mir gerade die Frage ob ichs vllt einfach an der falschen Stelle definiert hatte. Sowie ich vTaskSTartScheduler() in der main stehen hab gehts ohne umweg in den hard_fault_handler... das spricht doch eigentlich für einen heap bzw speicher fehler oder?
OK ich hab die #defines jetzt in die port.c gepackt und jetzt werde ich zwar nicht mehr in den hard_fault_handler geschickt aber dafür wird springt der mein programm nach vTaskStartScheduler() weiter... soll heißen er erreicht code nach vTaskStartScheduler()... das darf doch eigtl garnicht sein - hin oder her das ich noch keinen Task created hab... oder irre ich mich
Ok es funktioniert jetzt tatsächlich halbwegs! Ich habe einen Task erstellt der nix tut bis auf das er in einer while(1) Schleife endet. Und siehe da: wenn ich dort einen breakpoint setze, kommt er tatsächlich dort an! JIPPIE das is das aufregendste, was die letzten 2 Wochen passiert ist. Leider ist immernoch alles sehr wacklig... manchmal wird (komischerweise) der vTaskStartScheduler() mehrere mal aufgerufen bevor es in den eigtl Task geht. Ich vermute mal hier wird der Watchdog-Timer dazwischen funken... und nach einer weile lande ich dann doch wieder im Hard_Fault_Handler. Außerdem funktionert alles auch nur bei bestimmten heapx.c dateien. Im Moment bin ich bei Heap1... Bei den Demo-Projekten haben alle Heap3.c genommen, aber da lande ich wieder im Hard_FAULT_HANDLER... Also Danke Martin du hast mir schon sehr geholfen! Ich hoffe mir kann auch noch auf den letzten paar Metern geholfen werden... Das wär super!
Ja das stimmt. Die hatte ich ja vorher auch schon probiert bzw die Demos adaptiert dabei kam aber immer dasselbe heraus. Seitdem Martin das mit den #defines erklärt hatte läufts tatsächlich auch schon besser. Ich hatte gerade eben nochmal Sachen aus den Demos ausprobiert, allerdings bekam ich dabei wieder amoklaufende Programmzeiger... Irgendwas geht auf jeden Fall noch gehörig schief. Ich hab meine FreeRTOSConfig.h soweit runterreduziert, das wirklich absolut keine Sonderfunktionen "angeschaltet" sind. Es ist quasi der reine Kernel. Aber trotzdem ist bisher immernoch alles die reinstform von "undefiniertem Verhalten" Ich weiß auch immernoch nicht genau, was diese configMAX_SYSCALL_INTERRUPT_PRIORITY jetzt genau angibt. Ne Priorität - das ist klar! Aber was für eine? Weiß das zufällig jemand genauer?
Suche mal in den Freertos Quellen nach diesem Define. Da war was mit der höchsten die Freertos benutzt und da darf keine andere Rtos Funktion ausgeführt werden. Wenn man in diesem Fehler landet auf dem Callstack in die aufrufende Funktion gehen, da sind Kommentare im Quelltext zur Konfiguration. Habe die Quellen selber gerade nicht griffbereit.
Beim Heap muss man noch konfigurieren wieviel das Rtos verwalten soll. Das wird dann in der heap1/2/3 benutzt. Es darf nur eine von den dreien im Projekt aktiv sein, sind halt verschiedene Verwaltungsstrategien und man kann hier die optimale wählen. Die Tasks, Queues usw. Holen den Speicher über diese Funktionen und Rtos muss deshalb genug haben, es gibt auch eine Abfragefunktion dazu.
configMAX_SYSCALL_INTERRUPT_PRIORITY ist dafür da, dass die Interrupts nicht global deaktiviert werden sondern nur die RTOS Interrupts. Der Wert darf nicht 0 sein, da die Priorität 0 nicht deaktiviert werden kann beim Cortex. Du setzt den Wert auf irgendwas zwischen 0xE0 und 0x20. Dein M3 hat drei Prioritätsbits, 0bxxx00000. Daher die höhsten drei bits, also 5,6,7 geben die Priorität an. 0xE0 = 0b11100000 ist die niedrigeste Priorität. 0b00100000 ist die höchste. 0b00000000 ist noch höher, soll aber nicht verwendet werden. Wenn du jetzt "entercritical" aufrufst, wird das Basepri register auf den wert configMAX_SYSCALL_INTERRUPT_PRIORITY gesetzt. Damit werden alle Interrupts von RTOS gesperrt, aber andere Interrupts können noch ausgeführt werden.
Alles klar dankeschön! Das hat mich schon sehr viel weitergebracht. Leider hat sich im nachhinein herausgestellt dass das Hauptproblem - ich trau es mir garnicht zu sagen - ein falsch ausgewählter Chip war klatsch Trotzdem war das schon alles sehr hilfreich. Ich habe mir gedacht das ich jetzt einfach mal ein Tutorial hier ins Forum schreibe Beitrag für Beitrag... das wäre ja dann auch für andere interessant! Und je nachdem was ich dann für quatsch erzhähle und auch richtig schreibe kann man das dann hier kommentieren...
Tutorial Teil 1 - Die Verzeichnisstruktur Ich erstelle ein Projekt in meiner Entwicklungsumgebung, in diesem Fall mit LPCXpress von NXP. Dabei wähle ich ein LPCOpen Projekt, weil keine Lust hab mit den Adressen herumzuwirtschaften. Somit übernehme ich die Strukturen von den bereitgestellten cmsis Bibliotheken. Anschließend übernehme ich die Verzeichnis- und Dateistruktur von der aktuellsten FreeRTOS Version und intigriere sie in mein Projekt. Im Falle meines LPCXpress Projekts erstelle ich mir einen Ordner names "FreeRTOS" und entlade dort meine Verzeichnisstruktur (einschließlich Dateien die nicht zwangsläufig zum Kernel gehören) meinProjekt\FreeRTOS\croutine.c meinProjekt\FreeRTOS\event_groups.c meinProjekt\FreeRTOS\list.c meinProjekt\FreeRTOS\queue.c meinProjekt\FreeRTOS\taks.c meinProjekt\FreeRTOS\timers.c meinProjekt\FreeRTOS\include\ Zusätzlich natürlich die Dateien für die Portierung meines benutzten Mikrocontrollers, einem NXP LPC1547 mit einem ARM Cortex M3 Prozessor. Mein Compiler in LPCXpress ist mehr oder weniger ein GCC Compiler weswegen ich mich für FreeRTOS\Source\portable\GCC\ARM_CM3\ entscheide. Den Ordner (samt Inhalt natürlich) übernehme ich mit in mein "FREERTOS" Verzeichnis, also: FreeRTOS\portable\GCC\ARM_CM3\port.c FreeRTOS\portable\GCC\ARM_CM3\portmacro.h Alles anderen Ordner im "Source" Ordner kann ich weglassen. Da ich einem CM3 beackern will, füge ich in der port.c noch #define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler #define xPortSysTickHandler SysTick_Handler ein, weil dort die Handler für RTOS definiert bzw ersetzt werden. Da ich am Anfang das OS kennen lernen möchte, versuche ich natürlich alles so stabil und einfach wie möglich zu halten. Deswegen hole ich mir die FreeRTOS\Source\portable\MemMang\heap_3.c Datei, da diese eine einfache Umsetzung von den C-Befehlen malloc() & alloc() beinhaltet. (Steht auf jeden Fall so in der Beschreibung) Daher: meinProjekt\FreeRTOS\portable\MemMang\heap_3.c die anderen Heap_x.c dateien entfallen. Als letztes muss ich noch meine FreeRTOSConfig.h Datei in mein Projektverzeichnis anlegen. Hierfür habe ich alle defines die #define config... losgehen hineingeschrieben und alle die mit #define INCLUDE_... losgehen. In meinem Fall habe ich die aus der FreeRTOS_Reference_Manual zusammengetragen, allerdings gibts die auch in den weiten des Internets oder sind Bestandteil der mitgelieferten Demos von FreeRTOS. Dabei verpasse ich den config_KERNEL_INTERRUPT_PRIORITY den Wert 0xE0, da dieser das niedrigste Priority Level haben soll. configMAX_SYSCALL_INTERRUPT_PRIORITY bekommt den Wert 0xC0 da, weil er nicht sonderlich hoch sein soll, aber sich auch kein Priority Level mit dem Kernel teilen soll. Für configMINIMAL_STACK_SIZE wähle ich die Größe des Speichers für den IdleTask, der gestartet wird nachdem ich (nachher) den Scheduler starte. Ich setze ih auf 128, weil ich das für klein halte, ist aber mehr ein Schuss ins Blaue als Ahnung von der Materie. configMAX_PRIORITIES setze ich auf 7(oder 8??), weil ich drei bits zur Priority-Verteilung in meinem LPC15 habe. Dann setze ich noch meinen CPU Takt(configCPU_CLOCK_HZ auf 12000000), weil das die default-Einstellung in meinem Prozessor ist. Die Tickrate(configTICK_RATE_HZ) setze ich auf 100, in der Hoffnung das ich dann alle 10ms einen Tick bekomme! Dann wäre da noch configTOTAL_HEAP_SIZE auf 10024 zu setzen, eigtl unnötig, da für heap_3.c dieser Wert egal ist. Allerdings will ich später auch noch andere Heaps auprobieren und setze daher prophylaktisch diesen Wert ein. Woher ich den Wert hab? Von einem anderen Demo Board :) configMAX_TASK_NAME_LEN setze ich auf 16, weil ich bezweifle das ich meinen Tasks mehr als 16 Buchstaben geben werde. Für INCLUDE_vTaskDelay setze ich 1, da ich diese Funktion später in meinem Blinky Projekt benutzen möchte. Alles andere setze ich auf 0, da ich erstmal so wenig wie möglich funktionen aktiviert haben möchte, um das Betriebssystem gründlich kennen zu lernen. Wenn die FreeRTOSConfig.h fertig geschrieben ist, muss ich noch in meinen Project-Properties dem Compiler den Weg zu den Header-Dateien zeigen(Project->Properties->Settings->Includes)
Nochmal zu den heaps: du kannst alle drei übernehmen. Dann die zwei nicht aktiven mit der Option 'exclude from build' (irgendwo in dem ellenlangen Kontextmenü). Früher war im LPCXpresso sogar mal ein Wizard drin um ein FreeRTos Projekt zu generieren, das ist aber leider früh über Board gegangen.
Jojo S. schrieb: > das ist aber leider früh über Board gegangen. warum eigtl? Ist doch ne praktische Geschichte und wenns erstmal ist, warum dann wieder löschen? Das kapier ich nicht. Aber gut egal, was ich eigtl wissen wollte ist, hier reden immer alle von 3 heap-dateien... ich hab aber 5! ist das einfach nur ein versionsunterschied oder hat das einen tieferen sinn? Und was meinst du mit Kontext-Menü? Also du meinst ja bestimmt in einer Header Datei...?!
:
Bearbeitet durch User
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.