Hallo
Mit dem Pico-C/C++ SDK wollte ich in einem C-Programm den Flash-speicher
schreiben. Vorher muß man ja erst mal löschen. Dabei bin ich auf
Schwierigkeiten gestoßen, die meinen Pico beim Aufruf von flash erase
zum Absturz brachten. Nach stundenlangen Versuchen bin ich auf folgende
Verhaltensweisen gestoßen: 1 | In flash.h ist definiert:
| 2 | void flash_range_erase(uint32_t flash_offs, size_t count);
| 3 | #define FLASH_SECTOR_SIZE (1u << 12)
| 4 |
| 5 | In der Anwendung:
| 6 |
| 7 | flash_range_erase( w, 4 * FLASH_SECTOR_SIZE ); // ok
| 8 |
| 9 | #define defvier 4
| 10 | flash_range_erase( w, defvier * FLASH_SECTOR_SIZE) ); // geht nicht
| 11 |
| 12 | flash_range_erase( w, (size_t)(4 * FLASH_SECTOR_SIZE) ); // geht nicht
| 13 | flash_range_erase( w, (size_t)(defvier * FLASH_SECTOR_SIZE) ); // ok
| 14 |
| 15 |
| 16 | flash_range_erase( w, (int)(4 * FLASH_SECTOR_SIZE) ); // geht nicht
| 17 | flash_range_erase( w, (int)(defvier * FLASH_SECTOR_SIZE) ); // ok
| 18 |
| 19 | size_t vier = 4;
| 20 | flash_range_erase( w, vier * FLASH_SECTOR_SIZE ); // geht nicht
| 21 |
| 22 | int vier = 4;
| 23 | flash_range_erase( w, vier * FLASH_SECTOR_SIZE ); // ok
| 24 |
| 25 | int vier = defvier;
| 26 | flash_range_erase( w, vier * FLASH_SECTOR_SIZE ); // geht nicht
|
Das ganze verhält sich für mich nicht logisch nachvollziehbar, besonders
die letzten 2 Versuche. Kann mir da jemand auf die Sprünge helfen.
Besonders die Konstanden (hier 4) möchte ich schon mit #define
programmieren.
Vielleicht liegt das an dem unbekannten Inhalt von w, der zufällig ist?
Die Varianten sollten alle das gleiche Verhalten haben. Wenn also dein
Compiler nicht völlig kaputt ist, liegt das Problem wo anders.
N. M. schrieb:
> Nutzt du den 2. Core?
Nein. Und Nein, w ist immer gleich.
Ich hab noch mal nachgedacht. Zumindest den letzten Fall kann ich mir
erklären: der Compiler optimiert die Zuweisung von defvier in die
Variable vier weg und setzt defvier direkt in erase Anweisung ein. Somit
ist auch die vorletzte Zeile logisch, da die direkte Angabe von 4, wie
in Versuch 1 funktioniert. Bleibt die Frage warum defvier nicht geht?
Sieh Dir an, was der erzeugte Assemblercode ist.
Es sollte nur zwei Varianten geben, eine, bei der gleich die Konstante
16384 verwendet wird, und eine, bei der ein Wert (Registerinhalt o.ä.)
mit 4096 multipliziert wird.
kannst du in die Funktion reinsteppen und siehst dann mit welchem count
Wert die Funktion aufgerufen wird?
z.B.
flash_range_erase( w, (int)(4 * FLASH_SECTOR_SIZE) ); // geht
nicht
flash_range_erase( w, (int)(defvier * FLASH_SECTOR_SIZE) ); // ok
müßte ja exakt das selbe sein, da defvier durch 4 vom Preprocessor
ersetzt wird.
Sicher das da nicht etwas anderes in die Suppe spuckt?
Wenn das SDK in C++ geschrieben ist, solltest Du mal schauen, ob der von
Dir angegebene Prototyp der Funktion der einzige ist.
In C++ kann man nämlich Funktionen überladen. Also technisch gesehen,
verschiedene Funktionen mit dem selben Namen erstellen, die anhand der
Typen der übergebenen Parameter unterschieden werden.
Wenn die Funktionen dann wirklich das Selbe mit unterschiedlichen Daten
anstellen, ist sowas eine echte Erleichterung. Wenn unterschiedliche
Dinge passieren, abhängig davon, ob der 2. Parameter vorzeichenbehaftet
ist, stiftet es eher Verwirrung.
Flunder schrieb:
> Wenn das SDK in C++ geschrieben ist
Die HAL scheint in C zu sein.
Flunder schrieb:
> In C++ kann man nämlich Funktionen überladen.
Scheint hier nicht der Fall:
https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_flash/include/hardware/flash.h
@A.B. ..dachte ich auch. In der Original Version hat es nicht
funktioniert, deshalb hab ich eine extra Testfunktion probiert.
@Flunder Ist nur C.
@Harald Ich kann zwar Assembler, kenne aber noch nicht den Befehlssatz
und die Registerstruktur vom Pico. Um den Code zu vereinfachen habe nur
die Flash_erase fkt in Funktionsrumpf belassen. Nun hat der Compiller
die gesamte Funktion eleminiert, es ist kein Ass-Code mehr vorhanden.
Ist das sinnlos! Soll dabei der Flash nun nicht gelöscht werden?
was meinst du mit der extra Test Funktion? Evtl. musst du mal ein
minimal Programm bereitstellen bei dem das Auftritt
Nicht das hier irgendwas von zuschlägt
* \defgroup hardware_flash hardware_flash
*
* Low level flash programming and erase API
*
* Note these functions are unsafe if you are using both cores, and
the other
* is executing from flash concurrently with the operation. In this
could be the
* case, you must perform your own synchronisation to make sure that no
XIP
* accesses take place during flash programming. One option is to use
the
* \ref multicore_lockout functions.
*
* Likewise they are unsafe if you have interrupt handlers or an
interrupt
* vector table in flash, so you must disable interrupts before calling
in
* this case.
*
* If PICO_NO_FLASH=1 is not defined (i.e. if the program is built to
run from
* flash) then these functions will make a static copy of the second
stage
* bootloader in SRAM, and use this to reenter execute-in-place mode
after
* programming or erasing flash, so that they can safely be called from
* flash-resident code.
*
A. B. schrieb:
> * \defgroup hardware_flash hardware_flash
> *
> * Low level flash programming and erase API
> *
> * Note these functions are unsafe if you are using both cores, and
> the other
> * is executing from flash concurrently with the operation. In this
> could be the
> * case, you must perform your own synchronisation to make sure that no
> XIP
> * accesses take place during flash programming.
Aber so doof ist doch keiner, dass er sich selber seinen Flash unterm
Hintern wegschiesst.
Man ändert doch nicht Programmcode und Interrupt-Tabellen so
zwischendurch.
ich würde es eher interpretieren im Sinne von: während Flashlöschen
keine Codeausführung aus dem Flash(deshalb auch copy in RAM) und eben
noch zwei Cores.
Ich kenne die PicoArchitektur nicht weiter...aber ich würde einfach
denken das ihn da irgendetwas anders verarscht und es nicht unbedingt
mit den defines zusammenhängt
Du musst die Interrupte manuell sperren. Anonsten kann es passieren, das
während er den Flash schreibt ein Interrupt auftritt welcher Programm
Code aus dem XIP(Flash) erfordert. Dann knallts, weil der XIP währed
Flashzugriffen aus ist.
https://www.makermatrix.com/blog/read-and-write-data-with-the-pi-pico-onboard-flash/
Außerdem hoffe ich das Dein Offset nicht im Bereich des Programmcodes
liegt, sonst ziehst Du Dir selbst den Boden unter den Füßen weg
Andreas M. schrieb:
> Du musst die Interrupte manuell sperren.
Danke, das war es. Ich hab nur einen Interrupt, der aber selten läuft.
Deshalb gings mal und dann wieder nicht. Und da hat mir auch meine
komische Messreihe nicht geholfen.
Alle anderen Ursachen die hier erwähnt wurden hatte ich schon
ausgeschlossen.
Gruß Rudi
Nun hatte ich meinen Interrupt wieder gestartet. 1 | add_repeating_timer_ms(155, ledblink_callback, NULL, &LedBlink);
|
Und den Flash so programmiert: 1 | uint32_t ints = save_and_disable_interrupts();
| 2 | flash_range_program((PICO_FLASH_SIZE_BYTES - FLASH_SECTOR_SIZE), (uint8_t *)buf, FLASH_PAGE_SIZE);
| 3 | restore_interrupts (ints);
|
Funktioniert aber nicht! Pico blockiert wieder ab und zu beim Flashen.
Im SDK ist "add_repeating_timer" nicht bei den Interrupts aufgelistet.
Ist er am Ende keiner?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|