cancel
Showing results for 
Search instead for 
Did you mean: 

Receiving SPDIF data with STM32F446RET/CubeMX does not work

CDupu.1
Associate II

I'm trying to receive SPDIF data using an STM32F446RET using PB7 as SPDIFRX. The signal itself is perfect, a clear and sharp waveform can be seen directly at the input pin. The whole stuff is configured in CubeMX which also generated the code for interrupt data reception. From what I can see in the CubeMX-generated code, there is no obvious mistake. The major configuration looks like this:

   hspdif.Instance = SPDIFRX;
   hspdif.Init.InputSelection = SPDIFRX_INPUT_IN0;
   hspdif.Init.Retries = SPDIFRX_MAXRETRIES_63;
   hspdif.Init.WaitForActivity = SPDIFRX_WAITFORACTIVITY_ON;
   hspdif.Init.ChannelSelection = SPDIFRX_CHANNEL_A;
   hspdif.Init.DataFormat = SPDIFRX_DATAFORMAT_LSB;
   hspdif.Init.StereoMode = SPDIFRX_STEREOMODE_ENABLE;
   hspdif.Init.PreambleTypeMask = SPDIFRX_PREAMBLETYPEMASK_ON;
   hspdif.Init.ChannelStatusMask = SPDIFRX_CHANNELSTATUS_ON;
   hspdif.Init.ValidityBitMask = SPDIFRX_VALIDITYMASK_ON;
   hspdif.Init.ParityErrorMask = SPDIFRX_PARITYERRORMASK_ON;
   if (HAL_SPDIFRX_Init(&hspdif) != HAL_OK)
   {
      Error_Handler();
   }
  
  ...
   GPIO_InitStruct.Pin = GPIO_PIN_7;
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
   GPIO_InitStruct.Pull = GPIO_PULLUP;
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
   GPIO_InitStruct.Alternate = GPIO_AF8_SPDIFRX;
   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
   /* SPDIFRX interrupt Init */
   HAL_NVIC_SetPriority(SPDIF_RX_IRQn, 0, 5);
   HAL_NVIC_EnableIRQ(SPDIF_RX_IRQn);

Interrupts (both, global and the SPDIF-one) are enabled and data reception is initiated via a call to:

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

The interrupt routine to announce the completion of data reception looks like this:

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

So the whole code is more or less some straight-forward stuff which makes use if the HAL-interface's interrupt data transfer functionality.

My problem: this routine is never called. More than this, the low-level interrupt service function SPDIF_RX_IRQHandler() is also never called. One strange thing: I see the function SPDIF_RX_IRQHandler(), its definition but I can not see where it is defined as interrupt handler/where a pointer to this function is handed over to some IRQ hardware register.

As said, the SPDIF input signal is perfect, the only special thing here: it comes with 100 kHz clock, not 96 kHz or 192 kHz or something common like that.

So what could be the reason for my problems? Why are no SPDIF data received?

13 REPLIES 13

> So at 100 kHz you have a "symbol rate" of 100k * 32 * 2 = 6.4M, so spdifrx_ker_ck must at least be 70.4 MHz. At least for a STM32H7.

The same applies to 'F4, but the PLL is capable of generating such frequencies.

> The only exotic thing at my real-world SPDIF-data is the sample clock of the signal, it runs at 100 kHz (and not at 96 kHz like one would expect it from standard audio stuff).

If the loopback example generates 96kHz samples and it's capable of detecting its own signal but not the 100kHz signal, then the difference is in the timing setup. As I've said, reading/observing the RCC/SPDIFRX/GPIO registers' content and checking them against RM is the key.

JW

Piranha
Chief II

As already said by LCE, the SPDIFRX peripheral has two clocks - the peripheral and the SPDIFRX_CLK (acquisition/kernel) clock. Check whether you are providing an adequate SPDIFRX_CLK. The sample rate of your signal doesn't matter as long as the SPDIFRX_CLK >= (11 * sample_rate * 64). Though the higher the SPDIFRX_CLK frequency, the more robust the reception is, because the incoming signal is resampled with SPDIFRX_CLK. On your device the best is to feed it with 180 MHz.

I'm using SPDIFRX on F76x and it works like a charm. By the way, for such a non-trivial interface, it's super easy to manage. One can get it running with a single screen of code. And, by adding the second screen of code, one can also get the automatic re-synchronization, sample rate detection etc. Of course, I mean a normal code, not the HAL/Cube broken bloatware.

> Of course, I mean a normal code, not the HAL/Cube broken bloatware.

Is there an example of such a low-level SPDIF reception code available somewhere?

To understand what's going wrong, it would be the best for you to:

  • read the ref manual
  • understand the registers
  • copy & rename the most important HAL functions and understand what these are doing
  • modify the HAL functions, throw out what you don't need (there will be a lot)
    • I prefer to not use the HAL macros like SET_BIT / CLEAR_BIT, but do it like: PERIPH->EXAMPLE_REG &= ~EXAMPLE_REG_BIT_X;
  • check what the HAL functions might have missed, (e.g. interrupt settings)

That's basically how I "learned" the STM (work in progress...).

I still use some HAL functions for some not so important stuff, or after I checked them if I could do "better": many HAL functions are "bloated" because they're made to fit many applications - not yours.