Forum: Mikrocontroller und Digitale Elektronik STM32 - FMC: NAND Write blockiert Interrupts


von cc (Gast)


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

von Programmierer (Gast)


Lesenswert?

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.

von pegel (Gast)


Lesenswert?

Könnte das mit:

#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)

bzw. der Interrupt Prioritäten zu tun haben?

von Thorsten S. (thosch)


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

von Programmierer (Gast)


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?

von cc (Gast)


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

von Programmierer (Gast)


Lesenswert?

cc schrieb:
> Ich habe ein FreeRTOS am laufen und der Aufruf erfolgt in einem Task.

Funktioniert denn der Taskwechsel mittels (SysTick?) Timer Interrupt?

von cc (Gast)


Angehängte Dateien:

Lesenswert?

Hier übrigens die ganze Funktion - wer diese nicht selber suchen möchte. 
Die ITM_EVENTs habe ich eingefügt, um zu sehen welcher Teil wie lange 
benötigt und wo Interrupts blockiert werden. Von Abschalten der 
Interrupts ist leider nichts zu sehen...

von Peter D. (peda)


Lesenswert?

cc schrieb:
> Weiss jemand an was das liegt und wie man das beheben kann?

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.

von cc (Gast)


Lesenswert?

Programmierer schrieb:
> Funktioniert denn der Taskwechsel mittels (SysTick?) Timer Interrupt?

Ja, problemlos.

von RAc (Gast)


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
}

von cc (Gast)


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.

von cc (Gast)


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.

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.