RT1021 The TDM mode fs clock of the SAI is incorrect. Attached are the code of the configuration and the oscilloscope screenshot.
/* Select Audio/Video PLL (786.48 MHz) as sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_SELECT (2U)
/* Clock pre divider for sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER (1U)
/* Clock divider for sai1 clock source */
#define DEMO_SAI1_CLOCK_SOURCE_DIVIDER (15U)
/* Get frequency of sai1 clock */
#define DEMO_SAI_CLK_FREQ \
(CLOCK_GetFreq(kCLOCK_AudioPllClk) / (DEMO_SAI1_CLOCK_SOURCE_DIVIDER + 1U) / \
(DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER + 1U))
/* demo audio sample rate */
#define DEMO_AUDIO_SAMPLE_RATE (kSAI_SampleRate16KHz)
/* demo audio data channel */
#define DEMO_AUDIO_DATA_CHANNEL (2U)
/* demo audio bit width */
#define DEMO_AUDIO_BIT_WIDTH (kSAI_WordWidth16bits)
int SaiTask(void)
{
edma_config_t dmaConfig = {0};
char input = '1';
uint8_t userItem = 1U;
CLOCK_InitAudioPll(&audioPllConfig);
/* I2C */
/*Clock setting for LPI2C*/
CLOCK_SetMux(kCLOCK_Lpi2cMux, LPI2C_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, LPI2C_CLOCK_SOURCE_DIVIDER);
/*Clock setting for SAI1*/
CLOCK_SetMux(kCLOCK_Sai1Mux, DEMO_SAI1_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Sai1PreDiv, DEMO_SAI1_CLOCK_SOURCE_PRE_DIVIDER);
CLOCK_SetDiv(kCLOCK_Sai1Div, DEMO_SAI1_CLOCK_SOURCE_DIVIDER);
/*Enable MCLK clock*/
BOARD_EnableSaiMclkOutput(true);
/* Init DMAMUX */
DMAMUX_Init(DEMO_DMAMUX);
DMAMUX_SetSource(DEMO_DMAMUX, DEMO_TX_EDMA_CHANNEL, (uint8_t)DEMO_SAI_TX_SOURCE);
DMAMUX_EnableChannel(DEMO_DMAMUX, DEMO_TX_EDMA_CHANNEL);
DMAMUX_SetSource(DEMO_DMAMUX, DEMO_RX_EDMA_CHANNEL, (uint8_t)DEMO_SAI_RX_SOURCE);
DMAMUX_EnableChannel(DEMO_DMAMUX, DEMO_RX_EDMA_CHANNEL);
PRINTF("SAI Demo started!\n\r");
/* Create EDMA handle */
/*
* dmaConfig.enableRoundRobinArbitration = false;
* dmaConfig.enableHaltOnError = true;
* dmaConfig.enableContinuousLinkMode = false;
* dmaConfig.enableDebugMode = false;
*/
EDMA_GetDefaultConfig(&dmaConfig);
EDMA_Init(DEMO_DMA, &dmaConfig);
EDMA_CreateHandle(&dmaTxHandle, DEMO_DMA, DEMO_TX_EDMA_CHANNEL);
EDMA_CreateHandle(&dmaRxHandle, DEMO_DMA, DEMO_RX_EDMA_CHANNEL);
#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
EDMA_SetChannelMux(DEMO_DMA, DEMO_TX_EDMA_CHANNEL, DEMO_SAI_TX_EDMA_CHANNEL);
EDMA_SetChannelMux(DEMO_DMA, DEMO_RX_EDMA_CHANNEL, DEMO_SAI_RX_EDMA_CHANNEL);
#endif
/* SAI init */
SAI_Init(DEMO_SAI);
SAI_TransferTxCreateHandleEDMA(DEMO_SAI, &txHandle, txCallback, NULL, &dmaTxHandle);
SAI_TransferRxCreateHandleEDMA(DEMO_SAI, &rxHandle, rxCallback, NULL, &dmaRxHandle);
/* I2S mode configurations */
//SAI_GetClassicI2SConfig(&saiConfig, DEMO_AUDIO_BIT_WIDTH, kSAI_Stereo, 1U << DEMO_SAI_CHANNEL);
SAI_GetTDMConfig(&saiConfig, kSAI_FrameSyncLenOneBitClk, DEMO_AUDIO_BIT_WIDTH, DEMO_AUDIO_DATA_CHANNEL, 1U << DEMO_SAI_CHANNEL);
saiConfig.frameSync.frameSyncEarly = true;
//saiConfig.syncMode = DEMO_SAI_TX_SYNC_MODE;
//saiConfig.masterSlave = DEMO_SAI_MASTER_SLAVE;
SAI_TransferTxSetConfigEDMA(DEMO_SAI, &txHandle, &saiConfig);
//saiConfig.syncMode = DEMO_SAI_RX_SYNC_MODE;
SAI_TransferRxSetConfigEDMA(DEMO_SAI, &rxHandle, &saiConfig);
/* set bit clock divider */
SAI_TxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH,
DEMO_AUDIO_DATA_CHANNEL);
SAI_RxSetBitClockRate(DEMO_SAI, DEMO_AUDIO_MASTER_CLOCK, DEMO_AUDIO_SAMPLE_RATE, DEMO_AUDIO_BIT_WIDTH,
DEMO_AUDIO_DATA_CHANNEL);
/* master clock configurations */
BOARD_MASTER_CLOCK_CONFIG();
//tlv320
tlv6410_i2c_init();
tlv6410_config();
tlv6410_Status();
#if 0
/* Use default setting to init codec */
if (CODEC_Init(&codecHandle, &boardCodecConfig) != kStatus_Success)
{
assert(false);
}
if (CODEC_SetVolume(&codecHandle, kCODEC_PlayChannelHeadphoneLeft | kCODEC_PlayChannelHeadphoneRight,
DEMO_CODEC_VOLUME) != kStatus_Success)
{
assert(false);
}
#endif
/* Enable interrupt to handle FIFO error */
SAI_TxEnableInterrupts(DEMO_SAI, kSAI_FIFOErrorInterruptEnable);
SAI_RxEnableInterrupts(DEMO_SAI, kSAI_FIFOErrorInterruptEnable);
EnableIRQ(DEMO_SAI_TX_IRQ);
EnableIRQ(DEMO_SAI_RX_IRQ);
}
Solved! Go to Solution.
Hi @jarman_zhou ,
Now, both the DMA and the interrupt works.
1. DMA clock issues:
Check attached code:evkmimxrt1020_sai_edma_transfer_TDM_clock.zip
Just use the following clock configuration to the audio PLL.
const clock_audio_pll_config_t audioPllConfig = {
.loopDivider = 32, /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
.postDivider = 1, /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */
.numerator = 77, /* 30 bit numerator of fractional loop divider. */
.denominator = 100, /* 30 bit denominator of fractional loop divider */
};
Then you will find the MCLK is :12288750hz
BCLK is 512Khz
SYNC is 16Khz.
2. the interrupt issues, check your another post link:
I already share it with you.
If your issue is solved, please help to mark the correct answer, thanks.
Best Regards,
Kerry
Hi @jarman_zhou ,
Interrupt solutions, check this post reply:
Wish it helps you!
If you still have questions about it, please kindly let me know.
If your question is solved, please help to mark the correct answer, thanks.
Best Regards,
Kerry
Hi @jarman_zhou ,
What's the detail wave in your attached picture, SYNC, BCLK?
It's better to put it together.
Now, which frequency you want to get in SYNC? 16KHZ? then what's the result?
Please give me more description about your question, thanks.
Best Regards,
kerry
Look at the above code, after I changed the audio to TMD (SAI_GetTDMConfig), SAI data line IOMUXC_GPIO_AD_B1_03_SAI1_TX_DATA00 could not receive data, But when configured as I2S (SAI_GetClassicI2SConfig) there is data, the clock is always 16kHz, 16Bit, 2 channels.
If I want to configure it as TDM, is there anything missing in the above code? What should I configure?
Hi @jarman_zhou ,
Which SDK version you have test?
Please also attach your project which can reproduce the issues, then I will find time to test it on the MIMXRT1020-EVK board, thanks.
Best Regards,
kerry
Hi @jarman_zhou ,
So sorry for my later reply.
I find the issue is in the interrupt code, you can use the DMA method, that totally works.
Please check my attached code for the TDM, this is the test result when I sendout the following data:
__ALIGN_BEGIN const uint8_t music[] __ALIGN_END =
{
0x55, 0xaa, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00,
...
}
You can see the DMA method can output the data correctly.
Your configuration code is correct, just interrupt method have issues.
So, I suggest you use the DMA method at first.
Best Regards,
Kerry
Hi, @kerryzhou
I use the DMA method, The data is there, but I don't think the clock is right. I got the MCLK is 12000kHz and BCLK is 500kHz, FSync is 15.625kHz.
But i use the interrupt TDM, MCLK is 12288kHz and BCLK is 512kHz, FSync is 16kHz.
If the clock is wrong, I don't think the data is right.
Best Regards,
Jarman
Hi @jarman_zhou ,
Now, both the DMA and the interrupt works.
1. DMA clock issues:
Check attached code:evkmimxrt1020_sai_edma_transfer_TDM_clock.zip
Just use the following clock configuration to the audio PLL.
const clock_audio_pll_config_t audioPllConfig = {
.loopDivider = 32, /* PLL loop divider. Valid range for DIV_SELECT divider value: 27~54. */
.postDivider = 1, /* Divider after the PLL, should only be 1, 2, 4, 8, 16. */
.numerator = 77, /* 30 bit numerator of fractional loop divider. */
.denominator = 100, /* 30 bit denominator of fractional loop divider */
};
Then you will find the MCLK is :12288750hz
BCLK is 512Khz
SYNC is 16Khz.
2. the interrupt issues, check your another post link:
I already share it with you.
If your issue is solved, please help to mark the correct answer, thanks.
Best Regards,
Kerry