Forum: Mikrocontroller und Digitale Elektronik STM32H750 mit W25Q64 QSPI XIP memory mapped mode


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von epika (Gast)


Lesenswert?

Hallo,

hat jemand eine funktionierende Demo mit STM32H750 und W25Q64 QSPI im 
XIP memory mapped mode?
Programm im QSPI und flashloader Programm im internen Flash.

(am liebsten als STM32CubeIDE Projekt)

Danke

von A. B. (Gast)


Lesenswert?

Zunächst mal FV oder JV? Und wo soll da das Problem sein?
Man muss vor dem Einschalten des Memory Mapped Mode einmal ein Indirekt 
Read mit Instruktion und dem passenden Mode Byte (XIP an, als Alternate 
Byte) auslösen und dann beim Memory Mapped Mode keine Instruktion, ein 
Alternate Byte (mit dem passenden Mode Byte für XIP an) konfigurieren.
Und zum Ausschalten erstmal ein Abort, dann Indirekt Read ohne 
Instruktion, Adresse 0 und passendem Mode Byte (für XIP aus) auslösen.

Adresse 0, weil man u. U. nicht sicher sein kann, ob der Flash im 
XIP-Modus ist oder nicht, also das erste Byte der Adresse eventuell als 
Instruktion fehlinterpretiert werden könnte. Und 0x00 ist kein gültige 
Intruktion.

von epika (Gast)


Lesenswert?

A. B. schrieb:
> Zunächst mal FV oder JV?
JV ... spielt das eine Rolle im Code?

> Und wo soll da das Problem sein?
Also ich habe zuerst ein paar STM32 Beispiele mit dem STM32H750B Disco 
Board ausprobiert die mit Program-Code via externem QSPI laufen. Das 
funktioniert gut.
Das STM Beispiel-Projekt (ext Flash Booter) für den Code auf dem 
internen STM32-Flash lautet "ExtMem_Boot".

Ich habe jetzt ein ähnliches Board, aber mit einem (in China) besser 
erhältlichen QSPI von Windbond W25Q64JV (single).

Jetzt habe ich versucht das "ExtMem_Boot" Projekt so anzupassen, dass es 
für den W25Q64 passt.
Beim Debuggen verhält es sich jedoch anders, d.h. der externe Flash 
zeigt nach der "EnableMemoryMappedMode" Funktion überall den Inhalt 
888888888 und das Program geht dann in den void 
MemManage_Handler(void).... also irgendwas läuft was falsch.

Anpassungen habe ich im qspi.c und memory_msp.h File durchgeführt.
Das angepasste "ExtMem_Boot" Projekt findet man hier (Code im Bereich 
ifdef W25Q64):

https://drive.google.com/drive/folders/1n7dnF52jlO1vyJ8ENyKqWqMjwYVJ1sRY?usp=sharing

Die Anpassungen habe ich gemäss folgendem Projekt versucht zu übernehmen 
jedoch mit Pin-Mapping PB2,6, PF6,7,8,9 (das Board/Projekt ist/sollte 
für ein W25Q64 chip geschrieben sein):

https://github.com/osos11-https://github.com/osos11-Git/STM32H743VIT6_Boring_TECH_QSPI/tree/main/Memory%20Mapped%20Mode/H743_QSPI_XIP_1

> Man muss vor dem Einschalten des Memory Mapped Mode einmal ein Indirekt
> Read mit Instruktion und dem passenden Mode Byte (XIP an, als Alternate
> Byte) auslösen und dann beim Memory Mapped Mode keine Instruktion, ein
> Alternate Byte (mit dem passenden Mode Byte für XIP an) konfigurieren.
> Und zum Ausschalten erstmal ein Abort, dann Indirekt Read ohne
> Instruktion, Adresse 0 und passendem Mode Byte (für XIP aus) auslösen.
>
> Adresse 0, weil man u. U. nicht sicher sein kann, ob der Flash im
> XIP-Modus ist oder nicht, also das erste Byte der Adresse eventuell als
> Instruktion fehlinterpretiert werden könnte. Und 0x00 ist kein gültige
> Intruktion.


Die (HAL) Prozedur im Code ist aktuell wie folgt:
1
1.) QSPI GPIOs initialisieren
2
3
2.) ClockPrescaler, FifoThreshold, Sampleshifting, FlashSize, ChipSelectHighTime, ClockMode, FlashID=0?? initialisieren.
4
5
3.) ResetMemory
6
7
4.) AutoPollingMemReady
8
9
5.) Config (0x35 und 0x50 und 0x31 und 0x15 und 0x11 command instruction)
10
11
6.) EnableMemoryMappedMode




bin für jeden Hinweis dankbar...

von opzuiziziz (Gast)


Lesenswert?

das ist witzig .. hatte damit auch meine probleme ...
liegt am interrupt

ich habs dann zum laufen bekommen  zwar der W25Q16JV

mit den GPIOs den
    HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0);
    HAL_NVIC_EnableIRQ(QUADSPI_IRQn);

und die dummycycles richtig setzen
1
uint8_t CSP_QSPI_EnableMemoryMappedMode(void) {
2
3
  QSPI_CommandTypeDef sCommand = {0};
4
  QSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
5
6
  sCommand.InstructionMode     = QSPI_INSTRUCTION_1_LINE;
7
  sCommand.Instruction       = 0xEB;
8
  sCommand.AddressMode       = QSPI_ADDRESS_4_LINES;
9
  sCommand.DataMode         = QSPI_DATA_4_LINES;
10
  sCommand.NbData         = 0;
11
  sCommand.Address         = 0;
12
13
  switch ( jedecID ){
14
  case 0x1540ef:
15
  case 0x1640ef:
16
    sCommand.DummyCycles       = 6;
17
    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;
18
    break;
19
20
  case 0x1871f:
21
  case 0x1861f:
22
    sCommand.DummyCycles       = 4;
23
    sCommand.AddressSize       = QSPI_ADDRESS_32_BITS;
24
    break;
25
  }
26
27
  sMemMappedCfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
28
  sMemMappedCfg.TimeOutPeriod     = 0;
29
30
  if (QSPI_WriteEnable() != HAL_OK) {
31
    return HAL_ERROR;
32
  }
33
  if (HAL_QSPI_MemoryMapped(&hqspi, &sCommand, &sMemMappedCfg) != HAL_OK) {
34
    return HAL_ERROR;
35
  }
36
  return HAL_OK;
37
}

einen dummyread vorher machen

von opzuiziziz (Gast)


Lesenswert?

achso
das war der bootloader !!
die applikation fässt den QSPI nicht wieder an


ich hab ewig gesucht ...
erst mit aktivieren des QSPI interrupts funktioniert das mit dem memory 
mapped...

von opzuiziziz (Gast)


Lesenswert?

1
void MX_QUADSPI_Init(void){
2
  hqspi.Instance           = QUADSPI;
3
  hqspi.Init.ClockPrescaler     = 480/75;
4
  hqspi.Init.FifoThreshold     = 1;
5
  hqspi.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_NONE;
6
  hqspi.Init.FlashSize       = 20;
7
  hqspi.Init.ChipSelectHighTime   = QSPI_CS_HIGH_TIME_2_CYCLE;
8
  hqspi.Init.ClockMode       = QSPI_CLOCK_MODE_3;
9
  hqspi.Init.FlashID         = QSPI_FLASH_ID_1;
10
  hqspi.Init.DualFlash       = QSPI_DUALFLASH_DISABLE;
11
12
  if (HAL_QSPI_Init(&hqspi) != HAL_OK){
13
    Error_Handler();
14
  }
15
}
16
17
// bootloader main 
18
int main(void){
19
  SystemInit();
20
  HAL_Init();
21
  SystemClock_Config();
22
  SystemCoreClockUpdate();
23
  MX_GPIO_Init();
24
25
  if( CSP_QSPI_Init() != HAL_OK) {
26
    goto error;
27
  }
28
29
  volatile int firstbyte = 0;
30
  CSP_QSPI_ReadMemory(  (uint8_t*)&firstbyte , (0x000000), 4 );
31
32
  if (CSP_QSPI_EnableMemoryMappedMode() != HAL_OK){
33
    goto error;
34
  }
35
  if( *((uint32_t*) QSPI_BASE ) == 0xFFFFFFFF ){
36
    while(1);
37
  }
38
39
  SysTick->CTRL = 0 ;
40
  boot_jump( QSPI_BASE );
41
}

von epika (Gast)


Lesenswert?

opzuiziziz schrieb:
> erst mit aktivieren des QSPI interrupts funktioniert das mit dem memory
> mapped...

Ok, danke schon mal. Bei mir ist der Interrupt aktiviert, aber ich werde 
jetzt mal versuchen Schritt für Schritt deine Parameter zu übernehmen...

von opzuiziziz (Gast)


Lesenswert?

wichtig ist der adressmode(16/24/32 bit ) und die dummybytes

ich habe das so gemacht das erstmal grundlegend alle schreib / lese 
funktionen das tun was sie sollen

Danach erst den memory mapped

von A. B. (Gast)


Lesenswert?

epika schrieb:
> A. B. schrieb:
>> Zunächst mal FV oder JV?
> JV ... spielt das eine Rolle im Code?

Da manche Kommandos nur in einem der beiden verfügbar sind, ganz 
offensichtlich.

> Das STM Beispiel-Projekt (ext Flash Booter) für den Code auf dem
> internen STM32-Flash lautet "ExtMem_Boot".
>
> Ich habe jetzt ein ähnliches Board, aber mit einem (in China) besser
> erhältlichen QSPI von Windbond W25Q64JV (single).
>
> Jetzt habe ich versucht das "ExtMem_Boot" Projekt so anzupassen, dass es
> für den W25Q64 passt.
> Beim Debuggen verhält es sich jedoch anders, d.h. der externe Flash
> zeigt nach der "EnableMemoryMappedMode" Funktion überall den Inhalt
> 888888888 und das Program geht dann in den void
> MemManage_Handler(void).... also irgendwas läuft was falsch.

Die 88888888 ist eher ein Symptom, dass 1-Line/4-Line Modi zwischen 
QSPI-Interface und Flash nicht passen.

Man man aber strikt zwischen Programmausführung (nur Lesen, und zwar im 
Memory Mapped Mode) und Löschen/Schreiben/Konfigurieren unterscheiden. 
XIP geht nur,
wenn der Flash ausschließlich Reads bekommt.

> Die (HAL) Prozedur im Code ist aktuell wie folgt:
>
>
1
> 1.) QSPI GPIOs initialisieren
2
> 
3
> 2.) ClockPrescaler, FifoThreshold, Sampleshifting, FlashSize, 
4
> ChipSelectHighTime, ClockMode, FlashID=0?? initialisieren.
5
> 
6
> 3.) ResetMemory
7
> 
8
> 4.) AutoPollingMemReady
9
10
AutoPolling veträgt sich grundsätzlich nicht mit XIP, denn dabei werden
11
Read Status Reg. Kommandos gesendet. Bei Lesen ist AutoPolling aber ohnehin sinnfrei. 
12
 
13
> 5.) Config (0x35 und 0x50 und 0x31 und 0x15 und 0x11 command 
14
> instruction)
15
> 
16
> 6.) EnableMemoryMappedMode
17
>

Und das mit XIP? Das KANN so nicht gehen, denn der Flash bekommt dabei 
ja gar kein Befehlsbyte mehr. Es muss erst einmal das Read-Kommando 
(inkl. Befehlsbyte) geschickt werden, und am Ende des Kommandos gibt das 
Mode Byte an "bleibe in diesem Modus". Der erste Lesezugriff muss also 
MIT Befehlsbyte, alle weiteren müssen OHNE arbeiten. Also können die 
von vornherein nicht mit derselben Konfiguration des QSPI-Interface 
arbeiten. Nach dem "Anstoßen" des XIP-Modus muss also das QSPI-Interface 
umkonfiguriert werden, und das geht bekanntlich nur im "gestoppten" 
Zustand.

von epika (Gast)


Angehängte Dateien:

Lesenswert?

opzuiziziz schrieb:
> die dummycycles richtig setzen

Jetzt läuft schon mal was, vielen Dank :-D ...
Komisch nur, dass der erste Buchstabe von "Hello..." im Memory nicht 
abgebildet wird, aber im readbuf dann schon (siehe Anhang Bild).
Weiss jemand da was??

Änderungen:
Memory Mapped Mode von 0x6B auf 0xEB gewechselt, dummycycles von 8 auf 
6, und dann war "gpio_init_structure.Alternate" teils falsch gesetzt, 
AF9 statt AF10 oder umgekehrt. Für was ist Alternate überhaupt? Ist das 
entscheidend?

Vielen Dank für die Inputs.

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.