Rasperry Pico verwirrende Flash Programmierung

OP #7488373
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.

OP #7488550
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?

#7488594
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?

#7488657
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.

OP #7488700
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?

#7488743
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.
#7488792
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.

#7490107
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

#7490121
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

OP #7491264
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren