Forum: Mikrocontroller und Digitale Elektronik Rasperry Pico verwirrende Flash Programmierung


von Rudi (rudils)


Lesenswert?

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.

von N. M. (mani)


Lesenswert?

Nutzt du den 2. Core?

von Peter (pittyj)


Lesenswert?

Vielleicht liegt das an dem unbekannten Inhalt von w, der zufällig ist?

von Rolf M. (rmagnus)


Lesenswert?

Die Varianten sollten alle das gleiche Verhalten haben. Wenn also dein 
Compiler nicht völlig kaputt ist, liegt das Problem wo anders.

von Rudi (rudils)


Lesenswert?

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?

von Harald K. (kirnbichler)


Lesenswert?

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.

von A. B. (funky)


Lesenswert?

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?

von Flunder (flunder)


Lesenswert?

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.

von N. M. (mani)


Lesenswert?

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

von Rudi (rudils)


Lesenswert?

@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?

von A. B. (funky)


Lesenswert?

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.
 *

von Peter (pittyj)


Lesenswert?

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.

von A. B. (funky)


Lesenswert?

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

von Andreas M. (amesser)


Lesenswert?

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

von Rudi (rudils)


Lesenswert?

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

von Rudi (rudils)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.