MCUXpresso IDE v11.5.1 Compile SAI exception,See the code description
1.Loop assignment and individual assignment
2.Adds a print, but does not execute it
SDK_2_11_0_EVK-MIMXRT1020
Solved! Go to Solution.
Hi @jarman_zhou ,
我刚才直接跑了下你的代码,没有任何修改的情况下,是能听到声音采集传输回来的,就是有点杂音,没有完全变形。
然后我看了下你的代码,算了下你的几个大数组情况,已经很大了。如果是DTCM 配的0X8000,肯定是不够的。
情况这样:
16ms一次传输的数组: 6144byte, buffer定义了4个,就是6144*4=0X6000。
然后你又定义了其他几个整形数组:
int pTemp[BUFFER_SIZE/sizeof(int)] = {0};
int pMic[BUFFER_SIZE/sizeof(int)] = {0};
int pSendXfer[BUFFER_SIZE/sizeof(int)] = {0};
算下:6144*3=0X4800
总共:0X4800+6000=0XA800。
所以如果你定义0X8000,内存肯定是超了。
但是你想,我用SDRAM了,实际上SDRAM用做stack,还需要注意cache的情况,使用起来没那么顺畅。
所以,我建议你一个buffer可以做小点,就像你之前说的:如果将SIGLE_SAMPLE 改成8ms或者更小一点就正常。
这样耗费的stack会小一些,只是处理的勤快一点而已。
不知道,你那边是否能接收以代码换内存空间的方法?
实在不行,你把stack放大, heap减小点。stack可不能只是差不多0XA800,还得大,因为函数进出,中断进出,变量都得用,heap因为没有用malloc,我认为可以小。
RT1021的DTCM默认64K, 实在不够,你flexRAM重新分区,给DTCM搞大,OCRAM 搞小。
我算算,也是足够用了。可以把DTCM做到128K。
关于重新分区,可以参考我这个文章:
https://www.nxpic.org.cn/module/forum/thread-619452-1-1.html
我看你现在的map文件:
大小其实也是不行的。
所以目前两个建议:
1. 减小buffersize,我觉得也没必要一次处理时间太长,8ms,4ms其实都可以。
2.重新分区flexRAM, 把DTCM做到128K,然后stack size拉大,大过你所有的buffer空间,并且再加0x1000给其他耗用内存的用。
你那边试试看,如果还有问题,我们继续交流和测试!
Best Regards,
Kerry
Hi @jarman_zhou ,
I test your project on my MIMXRT1020-EVK, it meet the assert issue:
Do you have this issue?
Best Regards,
Kerry
Hi @jarman_zhou ,
Ok, I can test it based on the SDK directly.
One question, how do you know the data is incorrect, as you mentioned the sound is wrong with your related code, do you play the music?
Best Regards,
Kerry
Hi @jarman_zhou ,
我们可以直接用中文交流。
我先说下对你问题的理解,目前你是发现在DMA传输的过程重,添加了一些其他的操作,比如:
你现在是跑下面这段main出问题吗?我看你代码里两个main:
int main(void)
{
sai_transfer_t xfer, send_xfer;
edma_config_t dmaConfig = {0};
sai_transceiver_t saiConfig;
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
CLOCK_InitAudioPll(&audioPllConfig);
BOARD_InitDebugConsole();
/*Clock setting for LPI2C*/
CLOCK_SetMux(kCLOCK_Lpi2cMux, DEMO_LPI2C_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_Lpi2cDiv, DEMO_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 example started!\n\r");
/* Init DMA and create handle for DMA */
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, tx_callback, NULL, &dmaTxHandle);
SAI_TransferRxCreateHandleEDMA(DEMO_SAI, &rxHandle, rx_callback, 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.bitClock.bclkPolarity = DEMO_SAI_TX_BIT_CLOCK_POLARITY;
//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();
/* 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);
}
int pTemp[BUFFER_SIZE/sizeof(int)] = {0};
int pMic[BUFFER_SIZE/sizeof(int)] = {0};
int pSendXfer[BUFFER_SIZE/sizeof(int)] = {0};
send_xfer.data = pSendXfer;
send_xfer.dataSize = BUFFER_SIZE;
while (1)
{
if (rx_callback_finished)
{
rx_callback_finished = false;
//PRINTF("emptyBlock1=%d\r\n",emptyBlock);
xfer.data = Buffer + rx_index * BUFFER_SIZE;
xfer.dataSize = BUFFER_SIZE;
if (kStatus_Success == SAI_TransferReceiveEDMA(DEMO_SAI, &rxHandle, &xfer))
{
rx_index++;
}
if (rx_index == BUFFER_NUMBER)
{
rx_index = 0U;
}
}
if (tx_callback_finished)
{
tx_callback_finished = false;
xfer.data = Buffer + tx_index * BUFFER_SIZE;
xfer.dataSize = BUFFER_SIZE;
#if 1
memcpy(pTemp, xfer.data, BUFFER_SIZE);
for(int i=0; i<SIGLE_SAMPLE; i++)
{
for(int j=0; j<DEMO_AUDIO_DATA_CHANNEL; j++)
{
pMic[j*SIGLE_SAMPLE + i] = pTemp[DEMO_AUDIO_DATA_CHANNEL*i+j];
}
}
for(int i=0; i<SIGLE_SAMPLE; i++)
{
for(int j=0; j<DEMO_AUDIO_DATA_CHANNEL; j++)
{
//pMic[j*SIGLE_SAMPLE + i] = pMic[j*SIGLE_SAMPLE + i]<<1;//(1) Shift one bit to the right
//pMic[j*64 + i] = pMic[j*64 + i]<<1;//(2) Shift one bit to the left
//pMic[j*64 + i] = pMic[j*64 + i];
}
}
for(int i=0; i<SIGLE_SAMPLE; i++)
{
for(int j=0; j<DEMO_AUDIO_DATA_CHANNEL; j++)
{
pTemp[DEMO_AUDIO_DATA_CHANNEL*i+j] = pMic[j*SIGLE_SAMPLE + i];
}
}
memcpy(send_xfer.data, (void *)pTemp, BUFFER_SIZE);
#endif
if (kStatus_Success == SAI_TransferSendEDMA(DEMO_SAI, &txHandle, &send_xfer))
{
tx_index++;
}
if (tx_index == BUFFER_NUMBER)
{
tx_index = 0U;
}
}
}
}
最关键是这个代码加了出问题吗?
这个程序我是特意加大了EDMA的请求数据的大小
#define SIGLE_SAMPLE (DEMO_AUDIO_SAMPLE_RATE*16/1000)//16MS
#define BUFFER_SIZE (SIGLE_SAMPLE*DEMO_AUDIO_DATA_CHANNEL*sizeof(int))
这样经过处理之后就会有问题,如果将SIGLE_SAMPLE 改成8ms或者更小一点就正常。
处理数据,我只是简单的取出了每个通道的数据进行移位操作,相当于改变音量大小,并不会对数据正确性造成影响。后面音频正常后我会加入滤波器/EQ等算法。算法会处理多个通道的数据。
以上是EVK板上的情况。
事实上我调试自己的板子,只是采集数据直接给到播放时没有问题,但是一旦我加了如下的代码就会出现问题
Hi @jarman_zhou ,
我看下来也是和内存有关,所以你看看把工程的stack size, heap size放大看看,有没有用?
毕竟你的数组和你的长度直接有关,所以我想你把stack, heap都改大,在工程属性里面修改,这样linker file也会自动修改。
Best Regards,
Kerry
你目前stack heap size是多大?
你修改到最大是多大?
Hi @jarman_zhou ,
我刚才直接跑了下你的代码,没有任何修改的情况下,是能听到声音采集传输回来的,就是有点杂音,没有完全变形。
然后我看了下你的代码,算了下你的几个大数组情况,已经很大了。如果是DTCM 配的0X8000,肯定是不够的。
情况这样:
16ms一次传输的数组: 6144byte, buffer定义了4个,就是6144*4=0X6000。
然后你又定义了其他几个整形数组:
int pTemp[BUFFER_SIZE/sizeof(int)] = {0};
int pMic[BUFFER_SIZE/sizeof(int)] = {0};
int pSendXfer[BUFFER_SIZE/sizeof(int)] = {0};
算下:6144*3=0X4800
总共:0X4800+6000=0XA800。
所以如果你定义0X8000,内存肯定是超了。
但是你想,我用SDRAM了,实际上SDRAM用做stack,还需要注意cache的情况,使用起来没那么顺畅。
所以,我建议你一个buffer可以做小点,就像你之前说的:如果将SIGLE_SAMPLE 改成8ms或者更小一点就正常。
这样耗费的stack会小一些,只是处理的勤快一点而已。
不知道,你那边是否能接收以代码换内存空间的方法?
实在不行,你把stack放大, heap减小点。stack可不能只是差不多0XA800,还得大,因为函数进出,中断进出,变量都得用,heap因为没有用malloc,我认为可以小。
RT1021的DTCM默认64K, 实在不够,你flexRAM重新分区,给DTCM搞大,OCRAM 搞小。
我算算,也是足够用了。可以把DTCM做到128K。
关于重新分区,可以参考我这个文章:
https://www.nxpic.org.cn/module/forum/thread-619452-1-1.html
我看你现在的map文件:
大小其实也是不行的。
所以目前两个建议:
1. 减小buffersize,我觉得也没必要一次处理时间太长,8ms,4ms其实都可以。
2.重新分区flexRAM, 把DTCM做到128K,然后stack size拉大,大过你所有的buffer空间,并且再加0x1000给其他耗用内存的用。
你那边试试看,如果还有问题,我们继续交流和测试!
Best Regards,
Kerry
Hi @jarman_zhou ,
超过64K跑不起来,说明还是有问题,你是debug的吗?如果debug ,并且使用的是CMSIS DAP, 你要修改scp。
你这样,你打印下flexRAM的配置相关寄存器,看看是否改成功了。
另外,你把你最新的这个代码,就是超过64k的这个工程发我,我给你看看。
Best Regards,
kerry
Hi @jarman_zhou ,
我可以肯定,SAI可以和http一起跑,因为我之前做过一个天气预报,就是http+音频的,你可以看看我的文章:
关于代码debug,您可以帮我重新建一个帖子吗?因为这个问题时间太长了,超过4周我需要一直解释,所以麻烦您帮我重新建一个问题,我找个时间给你debug。
Best Regards,
Kerry
你好!
SDRAM使用没有问题,不过对于stack这些,我建议还是用内部的比较好点。
DTCM,ITCM不会受cache影响,而且速度快。 SDRAM是从SEMC接口走的,没有内部的快。
你还要做数据处理,而且DTCM也够用,我建议你用DTCM。
这个图比较清楚,你看到内核和DTCM, ITCM直接交互。但是OCRAM, SDRAM要走interconnect bus fabrics.用不好,会有冲突。
不过,用SDRAM了,你就把相关stack放到noncache区域中去,实在不行,关闭cache,具体你可以查看我们的AN12042。
你先使用DTCM改大看看,如果还是有问题,你更新后的工程再发我,我再复现你的问题。
Best Regards,
Kerry