STM32 - FMC: NAND Write blockiert Interrupts

Gast #6100227
Lesenswert?

Hallo,

ich habe ein NAND Flash am FMC eines STM32F446 am laufen. Bei einem Page 
Write durch die HAL Funktion 'HAL_NAND_Write_Page_8b' wird nach dem 
Schreiben der Status gepollt bis das NAND Flash die Daten verarbeitet 
hat, das passiert mit folgendem Code:
1
    while(HAL_NAND_Read_Status(hnand) != NAND_READY)
2
    {
3
      
4
      if((HAL_GetTick() - tickstart ) > NAND_WRITE_TIMEOUT)
5
      {
6
        return HAL_TIMEOUT; 
7
      }
8
    }

Die Schleife dauert bei mir ca. 276us. In dieser Zeit kommen bei mir 
keine anderen Interrupts durch. Da ich zyklisch einen ADC abfrage ist 
mir dies aufgefallen.

Die Funktion HAL_NAND_Read_Status sieht so aus:
1
uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand)
2
{
3
  uint32_t data = 0U;
4
  uint32_t deviceaddress = 0U;
5
  
6
  /* Identify the device address */
7
  if(hnand->Init.NandBank == FMC_NAND_BANK2)
8
  {
9
    deviceaddress = NAND_DEVICE1;
10
  }
11
  else
12
  {
13
    deviceaddress = NAND_DEVICE2;
14
  } 
15

16
  /* Send Read status operation command */
17
  *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
18
  
19
  /* Read status register data */
20
  data = *(__IO uint8_t *)deviceaddress;
21

22
  /* Return the status */
23
  if((data & NAND_ERROR) == NAND_ERROR)
24
  {
25
    return NAND_ERROR;
26
  } 
27
  else if((data & NAND_READY) == NAND_READY)
28
  {
29
    return NAND_READY;
30
  }
31

32
  return NAND_BUSY; 
33
}

Weiss jemand an was das liegt und wie man das beheben kann? Ich habe 
schon sämtliche Datenblätter von ST durch aber nichts zu dem Thema 
gefunden.

Viele Gruesse
cc
#6100261
Lesenswert?

Programmierer schrieb:
> Hast du mal versucht, den ISR-Vektor und den ISR-Code selbst in den RAM
> zu verlegen? Vielleicht wird der Zugriff auf den internen Flash
> irgendwie blockiert/verzögert.

Es geht hier um externes NAND Flash am FMC.
Mit dem internen NOR Flash des Controllers, in dem defaultmäßig auch die 
Vektortabelle steht, hat das gar nichts zu tun...

Das Problem hier dürfte an der Verwendung blockierender HAL Routinen 
liegen. Hab mich mit dem FMC bislang nicht beschäftigt, aber bei anderer 
Peripherie gibt's statt der blockierenden Varianten auch immer welche, 
die nichtblockierend über Callback-Interrupts arbeiten...
Gast #6100267
Lesenswert?

Thorsten S. schrieb:
> Es geht hier um externes NAND Flash am FMC.

Ich weiß.

Thorsten S. schrieb:
> .
> Mit dem internen NOR Flash des Controllers, in dem defaultmäßig auch die
> Vektortabelle steht, hat das gar nichts zu tun...

Würde man denken. Aber wer weiß, wie sich das beeinflusst und was da 
durch die selbe Logik geht.

Thorsten S. schrieb:
> Das Problem hier dürfte an der Verwendung blockierender HAL Routinen
> liegen.

In denen ist aber nichts von deaktivierten Interrupts zu sehen. Oder 
vielleicht in der nicht gezeigten HAL_NAND_Write_Page_8b Funktion?
Gast #6100268
Lesenswert?

Programmierer schrieb:
> Hast du mal versucht, den ISR-Vektor und den ISR-Code selbst in
> den RAM
> zu verlegen? Vielleicht wird der Zugriff auf den internen Flash
> irgendwie blockiert/verzögert.

Nein, der interne Flash sollte ja genau so wenig/viel beeinflusst sein 
wie der RAM. Zudem ist der RAM schon knapp ;)

pegel schrieb:
> Könnte das mit:
>
> #if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
>
> bzw. der Interrupt Prioritäten zu tun haben?

Thorsten S. schrieb:
> Das Problem hier dürfte an der Verwendung blockierender HAL Routinen
> liegen. Hab mich mit dem FMC bislang nicht beschäftigt, aber bei anderer
> Peripherie gibt's statt der blockierenden Varianten auch immer welche,
> die nichtblockierend über Callback-Interrupts arbeiten...

Ich habe ein FreeRTOS am laufen und der Aufruf erfolgt in einem Task. 
Die Interrupt-Priorität der anderen Interrupts sind auf 0, d.h. diese 
würden auf jeden Fall durchkommen. Vor dem Polling des Status kommen 
diese ja auch durch.

Die Zeile
1
  data = *(__IO uint8_t *)deviceaddress;
benötigt übrigens 20 Cycles habe ich gerade gesehen. Sonst wäre mir 
nichts aufgefallen was die Interrupts beeinflussen könnte. Bin weiter 
ratlos...
Gast #6100403
Lesenswert?

Hallo,

such doch bitte mal raus, wie bei Dir die HAL_GetTick() implementiert 
ist. Das ist eine weak, die in der Defaultimplementation ohne 
Manipulation der Interruptmaske einen Zähler abfragt, der mit dem HAL 
1ms Timer ISR inkrementiert wird (das ist eines der Dinge, die ich an 
der ST HAL nicht mag). Es kann aber auch sein, dass die auf 
xTaskGetTickCount() gemappt wird, und da hast Du genau das Problem, das 
Peter in die Diskussion gebracht hat:
1
TickType_t xTaskGetTickCount( void )
2
{
3
TickType_t xTicks;
4

5
  /* Critical section required if running on a 16 bit processor. */
6
  taskENTER_CRITICAL();   <==== !!!!!!
7
  {
8
    xTicks = xTickCount;
9
  }
10
  taskEXIT_CRITICAL();    <==== !!!!!!
11

12
  return xTicks;
13
}
Gast #6100404
Lesenswert?

Peter D. schrieb:
> Irgendeine der HAL-Funktionen wird eine höhere Priorität haben, als der
> ADC-Interrupt und ihn daher ständig unterbrechen.
> Ich hätte da HAL_GetTick() in Verdacht.

Nein, das ist lediglich eine Getter Funktion die eine Variable 
zurückgibt. Die ganzen Libraries sind ja an sich nur C code welche keine 
Priorität im Sinn eines Interrupts besitzen können.

Das Auslesen des NAND-Status, welches beim schrittweise Debuggen 20 
Taktzyklen braucht benötigt - wenn ich vorher und nachher den 
Cyclecounter des Kerns auslese doch wesentlich länger, eher so im 
Bereich 300us. Das könnte das Problem sein.
Gast #6100407
Lesenswert?

RAc schrieb:
> such doch bitte mal raus, wie bei Dir die HAL_GetTick() implementiert
> ist. Das ist eine weak, die in der Defaultimplementation ohne
> Manipulation der Interruptmaske einen Zähler abfragt, der mit dem HAL
> 1ms Timer ISR inkrementiert wird (das ist eines der Dinge, die ich an
> der ST HAL nicht mag). Es kann aber auch sein, dass die auf
> xTaskGetTickCount() gemappt wird, und da hast Du genau das Problem, das
> Peter in die Diskussion gebracht hat:

Nein, wird nicht überschrieben. Die Funktion wird hier auch gar nie 
aufgerufen, die Funktion HAL_NAND_Read_Status liefert beim ersten Aufruf 
das OK.

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