STM32 empfängt keine SPDIF-Daten

Gast #7346660

Ich versuche hier, mit einem STM32F466RE einen SPDIF-Datenstrom an PB7 zu empfangen. Der Code ist mit CubeMX erzeugt und sollte daher eigentlich passen, wenn ich mir ansehe, was CubeMX generiert hat, kann ich keinen offensichtlichen Fehler erkennen. Der SPDIF-Datenstrom ist - direkt am Eingangspin gemessen - ein perfektes und astrein sauberes Signal. Der zugehörige sowie die globalen Interrupts sind aktiviert. Trotzdem wird nichts empfangen, die Receive-Interruptfunktion wird nie aufgerufen:

1
void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hspdif)
2
{
3
   spdifRecvComplete=1;
4
}

Die Initialisierung von CubeMX sieht inklusive des Pinmappings so aus (zumindest die relevanten Teile, der Rest ist ja eh' der immer gleiche, generierte Code):

1
   hspdif.Instance = SPDIFRX;
2
   hspdif.Init.InputSelection = SPDIFRX_INPUT_IN0;
3
   hspdif.Init.Retries = SPDIFRX_MAXRETRIES_63;
4
   hspdif.Init.WaitForActivity = SPDIFRX_WAITFORACTIVITY_ON;
5
   hspdif.Init.ChannelSelection = SPDIFRX_CHANNEL_A;
6
   hspdif.Init.DataFormat = SPDIFRX_DATAFORMAT_LSB;
7
   hspdif.Init.StereoMode = SPDIFRX_STEREOMODE_ENABLE;
8
   hspdif.Init.PreambleTypeMask = SPDIFRX_PREAMBLETYPEMASK_ON;
9
   hspdif.Init.ChannelStatusMask = SPDIFRX_CHANNELSTATUS_ON;
10
   hspdif.Init.ValidityBitMask = SPDIFRX_VALIDITYMASK_ON;
11
   hspdif.Init.ParityErrorMask = SPDIFRX_PARITYERRORMASK_ON;
12
   if (HAL_SPDIFRX_Init(&hspdif) != HAL_OK)
13
   {
14
      Error_Handler();
15
   }
16
  
17
  ...
18

19
   GPIO_InitStruct.Pin = GPIO_PIN_7;
20
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
21
   GPIO_InitStruct.Pull = GPIO_PULLUP;
22
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
23
   GPIO_InitStruct.Alternate = GPIO_AF8_SPDIFRX;
24
   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
25

26
   /* SPDIFRX interrupt Init */
27
   HAL_NVIC_SetPriority(SPDIF_RX_IRQn, 0, 5);
28
   HAL_NVIC_EnableIRQ(SPDIF_RX_IRQn);

An der Funktion, die den Empfang der Daten starten sollte, ist auch nichts dramatisch kompliziertes:

1
if (HAL_SPDIFRX_ReceiveDataFlow_IT(&hspdif,recvBuffer,8)==HAL_OK)
2
{
3
   spdifRecvComplete=0;
4
}

Google hilft nicht wirklich weiter, entweder finde ich Beispielcode, der auch nur aus CubeMX stammt, oder der für einen anderen STM32-Typen ist und letztenendes auch keine Erkenntnisse bringt, die das Problem lösen würden.

Das Einzige, was in meinem Fall speziell ist: die eingehenden Daten haben 100 kHz statt 96 kHz oder 192 khz oder irgend ein anderes Vielfaches von 24 kHz - aber ich kann nirgendwo im Handbuch erkennen, dass das ein Problem wäre, es ist nur von einer Maxialfrequenz von 192 kHz die Rede.

Was könnte hier falsch sein/fehlen?

Gast #7346686

Lothar J. schrieb:

IRQ Receive Routine?

...wird von dem CubeMX-Code gemacht. Wenn es so funktioniert, wie es soll, erhalte ich ein "Receive Complete" über die Funktion HAL_SPDIFRX_RxCpltCallback() und finde dann die empfangenen Daten in meinem per HAL_SPDIFRX_ReceiveDataFlow_IT() übergebenen recvBuffer. Aber eben dieses "Receive Complete" kommt nie.

#7346715

Shinner schrieb:

...wird von dem CubeMX-Code gemacht. Wenn es so funktioniert, wie es soll, erhalte ich ein "Receive Complete" über die Funktion HAL_SPDIFRX_RxCpltCallback() und finde dann die empfangenen Daten in meinem per HAL_SPDIFRX_ReceiveDataFlow_IT() übergebenen recvBuffer. Aber eben dieses "Receive Complete" kommt nie.

Dann würde ich in dieser IRQ Routine suchen per Debugger.
Meine Erfahrungen kommen aus der EFM32 Ecke, die sind ja ähnlich und eine HAL gibt es da auch. Nur hat die selten vollständigen Code generiert, wie soll sie auch.

Blackbird

Gast #7346965

Das wäre SPDIF_RX_IRQHandler() - die wird niemals aufgerufen.

Tatsächlich kann ich nicht erkennen, wo die jemals als IRQ-Einsprungpunkt gesetzt werden würde. Allerdings sehe ich das bei USART2_IRQHandler() auch nicht, aber der UART-Interrupt funktioniert.

Gast #7347237

Shinner schrieb:

Tatsächlich kann ich nicht erkennen, wo die jemals als IRQ-Einsprungpunkt gesetzt werden würde.

Üblicherweise ist diese Funktion in der Datei <stm32f4xx_it.c> zu finden ....

1
/******************************************************************************/
2
/* STM32F4xx Peripheral Interrupt Handlers                                    */
3
/* Add here the Interrupt Handlers for the used peripherals.                  */
4
/* For the available peripheral interrupt handler names,                      */
5
/* please refer to the startup file (startup_stm32f4xx.s).                    */
6
/******************************************************************************/
7
/**
8
  * @brief This function handles SPDIF-RX global interrupt.
9
  */
10
void SPDIF_RX_IRQHandler(void)
11
{
12
  /* USER CODE BEGIN SPDIF_RX_IRQn 0 */
13

14
  /* USER CODE END SPDIF_RX_IRQn 0 */
15
  HAL_SPDIFRX_IRQHandler(&hspdif);
16
  /* USER CODE BEGIN SPDIF_RX_IRQn 1 */
17

18
  /* USER CODE END SPDIF_RX_IRQn 1 */
19
}
Gast #7347312

mitlesa schrieb:

Shinner schrieb:

Tatsächlich kann ich nicht erkennen, wo die jemals als IRQ-Einsprungpunkt gesetzt werden würde.

Üblicherweise ist diese Funktion in der Datei <stm32f4xx_it.c> zu finden ....

Nein, die Funktion selber ist im Usercode zu finden, weil dort auch das SPDIF-Handle liegt, welches für die weitere Bearbietung des Interrupt benötigt wird.

Die Frage ist, wo wird der POINTER auf diese Funktion in die Hardware geschrieben? Das muss ja irgendwo passieren, so dass der Interrupt weiß, wo hingesprungen werden muss. Und diese Zuweisung Hardware Interrupt -> aufzurufende Funktion SPDIF_RX_IRQHandler() fehlt mir hier irgendwie komplett.

#7347325

mitlesa hat schon recht

normalerweise ist SPDIF_RX_IRQHandler als weak definiert in einem deiner startup files. startup_stm32f...s dürfte das heißen

dort findest du dann ein EXPORT SPDIF_RX_IRQHandler [WEAK] und das wird in der xxx_it.c implementiert. Dort wird dann der HAL IRQHandler aufgerufen, der dann wiederum deinen callback aufruft.

Gast #7347415

A. B. schrieb:

normalerweise ist SPDIF_RX_IRQHandler als weak definiert

Auch dann fehlt mir die Verbindung zwischen Code und Hardware! Die MCU springt ja keinen String "SPDIF_RX_IRQHandler" an, sondern eine Adresse, hinter der sich dieser IRQ-Handler verbirgt, der halt zufällig "SPDIF_RX_IRQHandler" heißt.

Gast #7347787

Shinner schrieb:

Auch dann fehlt mir die Verbindung zwischen Code und Hardware! Die MCU springt ja keinen String "SPDIF_RX_IRQHandler" an, sondern eine Adresse, hinter der sich dieser IRQ-Handler verbirgt, der halt zufällig "SPDIF_RX_IRQHandler" heißt.

Das klingt deutlich nach Beratungsresistenz bzw. Faulheit einfach nachzusehen wo was ist. Also hier noch im Detail für die Faulen unter uns: Im Anhang ein Auszug aus <startup_stm32f446xx.s>. Dort sind am Anfang viele 32-Bit Worte (also Vektoren) definiert wobei für jeden Offset von Null ein bestimmter auf die Hardware zugeschnittener Platz für einen Interrupt reserviert ist. Der Offset bestimmt welcher Hardware-IRQ gemeint ist, der Wert bestimmt wo hingesprungen werden soll. Wer's jetzt nicht kapiert dem ist nicht mehr zu helfen.

Angehängte Dateien:
#7406608

Ich finde das Thema S/P-DIF mit STM32 hochspannend. Denn es gibt von TI Class-D Verstärkerchips, die einen Digital-Eingang haben und man kann mit dem STM32 dann auch über die I2C Schnittstelle bei dem TI Class-D Verstärker einiges einstellen, z.b. Mehrkanal-EQ, Lautstärke etc. Mit einem Bluetoothmodul könnte man auch eine Fernbedienung übers Handy realisieren, etc. Aktivboxen mit digitaler Frequenzweiche, die Frequenzcharakteristik übers Handy konfiguieren etc. Raumkorrektur. Da wäre ein STM32 in der Mitte als Controller mit SP-DIF Eingang für den ganzen Spaß eine interessante Option.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 3 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.