Skip to content

Commit

Permalink
drivers: sai: the 1st frame synchronization signal lost in slave side
Browse files Browse the repository at this point in the history
According the RM document, RT1170 58.3.3 (should be same for other MCU
which has a similiar SAI IP):
"A valid frame sync is also ignored (slave mode) or not generated (master
mode) for the first four bit clock cycles after enabling the transmitter
or receiver."
but in fact, we found master side send out a valid frame sync at the 3rd
bit clock cycles which cause this frame sync is ignored by the slave
side and frame data lost.
To workaround this issue, bit clock is enabled before TE/RE.

Signed-off-by: Raymond Lei <[email protected]>
  • Loading branch information
Raymond0225 committed Dec 17, 2024
1 parent 0ac8302 commit 429891d
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions mcux/mcux-sdk/drivers/sai/fsl_sai.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,15 @@ void SAI_TxEnable(I2S_Type *base, bool enable)
/* If clock is sync with Rx, should enable RE bit. */
if (((base->TCR2 & I2S_TCR2_SYNC_MASK) >> I2S_TCR2_SYNC_SHIFT) == 0x1U)
{
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_BCE_MASK);
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK);
}
/* Sometimes, bit clock starts just 3 clocks before frame synchronization
* signal, which cause the 1st frame sync is ignored by the RX side as
* described in RT1170 RM 58.3.3. To make bit clock at least 4 clocks earlier,
* here, we enable bit clock firstly.
*/
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_BCE_MASK);
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK);
/* Also need to clear the FIFO error flag before start */
SAI_TxClearStatusFlags(base, kSAI_FIFOErrorFlag);
Expand All @@ -520,8 +527,10 @@ void SAI_TxEnable(I2S_Type *base, bool enable)
/* If Rx not in sync with Tx, then disable Tx, otherwise, shall not disable Tx */
if (((base->RCR2 & I2S_RCR2_SYNC_MASK) >> I2S_RCR2_SYNC_SHIFT) != 0x1U)
{
/* Disable TE bit */
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~I2S_TCSR_TE_MASK));
/* Disable TE bit. Bit clock will not be disabled by disabling TE bit, we need
* disable it at the same time.
*/
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) & (~(I2S_TCSR_TE_MASK | I2S_TCSR_BCE_MASK)));
}
}
}
Expand All @@ -539,8 +548,15 @@ void SAI_RxEnable(I2S_Type *base, bool enable)
/* If clock is sync with Tx, should enable TE bit. */
if (((base->RCR2 & I2S_RCR2_SYNC_MASK) >> I2S_RCR2_SYNC_SHIFT) == 0x1U)
{
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_BCE_MASK);
base->TCSR = ((base->TCSR & 0xFFE3FFFFU) | I2S_TCSR_TE_MASK);
}
/* Sometimes, bit clock starts just 3 clocks before frame synchronization
* signal, which cause the 1st frame sync is ignored by the RX side as
* described in RT1170 RM 58.3.3. To make bit clock at least 4 clocks earlier,
* here, we enable bit clock firstly.
*/
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_BCE_MASK);
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) | I2S_RCSR_RE_MASK);
/* Also need to clear the FIFO error flag before start */
SAI_RxClearStatusFlags(base, kSAI_FIFOErrorFlag);
Expand All @@ -550,8 +566,10 @@ void SAI_RxEnable(I2S_Type *base, bool enable)
/* If Tx not in sync with Rx, then disable Rx, otherwise, shall not disable Rx */
if (((base->TCR2 & I2S_TCR2_SYNC_MASK) >> I2S_TCR2_SYNC_SHIFT) != 0x1U)
{
/* Disable RE bit */
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~I2S_RCSR_RE_MASK));
/* Disable RE bit. Bit clock will not be disabled by disabling RE bit, we need
* disable it at the same time.
*/
base->RCSR = ((base->RCSR & 0xFFE3FFFFU) & (~(I2S_RCSR_RE_MASK | I2S_RCSR_BCE_MASK)));
}
}
}
Expand Down Expand Up @@ -851,7 +869,8 @@ void SAI_TxSetBitclockConfig(I2S_Type *base, sai_master_slave_t masterSlave, sai
}
else
{
tcr2 &= ~(I2S_TCR2_BCD_MASK);
/* Clear BCP bit before set it. */
tcr2 &= ~(I2S_TCR2_BCD_MASK | I2S_TCR2_BCP_MASK);
tcr2 |= I2S_TCR2_BCP(config->bclkPolarity);
}

Expand Down Expand Up @@ -879,7 +898,8 @@ void SAI_RxSetBitclockConfig(I2S_Type *base, sai_master_slave_t masterSlave, sai
}
else
{
rcr2 &= ~(I2S_RCR2_BCD_MASK);
/* Clear BCP bit before set it. */
rcr2 &= ~(I2S_RCR2_BCD_MASK | I2S_RCR2_BCP_MASK);
rcr2 |= I2S_RCR2_BCP(config->bclkPolarity);
}

Expand Down

0 comments on commit 429891d

Please sign in to comment.