cancel
Showing results for 
Search instead for 
Did you mean: 

I2S clock strobing

_andreas
Senior

The stm32u5xx_hal_sai.c sets up the I2S clock strobing like this:

static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot)
{
  HAL_StatusTypeDef status = HAL_OK;
 
  hsai->Init.Protocol            = SAI_FREE_PROTOCOL;
  hsai->Init.FirstBit            = SAI_FIRSTBIT_MSB;
  /* Compute ClockStrobing according AudioMode */
  if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
  {
    /* Transmit */
    hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_FALLINGEDGE;
  }
  else
  {
    /* Receive */
    hsai->Init.ClockStrobing     = SAI_CLOCKSTROBING_RISINGEDGE;
  }

Notice the dependency on the TX or RX direction. However, the I2S standard uses a fixed definition: setup on falling for the transmitter, sample on rising for the receiver.

The reference manual states:

Bit 9 CKSTR: Clock strobing edge
This bit is set and cleared by software. It must be configured when the audio block is disabled. This
bit has no meaning in SPDIF audio protocol.
0: Signals generated by the SAI change on SCK rising edge, while signals received by the SAI are
sampled on the SCK falling edge.
1: Signals generated by the SAI change on SCK falling edge, while signals received by the SAI are
sampled on the SCK rising edge.

So the only valid setting is 1 (SAI_CLOCKSTROBING_RISINGEDGE) for conform I2S.

Why does the HAL implementation deviate?

3 REPLIES 3
Piranha
Chief II

It appears that it is confusing but correct. The code you showed just initializes the configuration structure. The peripheral is initialized by HAL_SAI_Init().

https://community.st.com/s/question/0D50X00009XkaCCSAZ/f446-cubedocumentation-saixycr1ckstr

If you would have looked into the init code, you would have noticed that it just shifts this value to the correct position in the peripheral register. Since it does not add any information, I left that as an exercise the reader.
_andreas
Senior

Ok - the init code turns everything back again:

  /* Compute CKSTR bits of SAI CR1 according ClockStrobing and AudioMode */
  if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX))
  {
    /* Transmit */
    ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR;
  }
  else
  {
    /* Receive */
    ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U;
  }