Other Parts Discussed in Thread: TLV320AIC3120, SIMPLELINK-CC13XX-CC26XX-SDK, Z-STACK
Hello all,
i've strange issue related to the i2s peripheral. I'll try to describe it as detailed as i can.
I'm developing a device which can connect to the zigbee network and act as a doorbell.
Audio samples are stored in external flash memory. When trigger comes from the zigbee network, audio data is read from
external flash and transmitted to the audio codec via I2S peripheral. In general it works well, but i'm struggling with one strange case.
Namely if there was performed pairing process and then the trigger comes, played melody doesn't sound as expected (it's something like noise or wheezes).
As i said it appears only if the pairing was performed. No matter how much time will pass since the pairing process after play trigger i hear noise. But if i reset the
device and then send trigger again, melody is played well.
Now some technical info
I'm using SimpleLink SDK 4.30.
MCU: CC2652R1
Audio Codec: TLV320AIC3120
The audio player module is running in separate task, which is synchronized by semaphore with I2S write callback.
This task is also highest priority task in my app.
Here you can see some pseudocode (as i'm not able to share the real one with you).
Audio player task and i2s write callback:
/* Wait for semaphore posted from I2S write callback. */
bool Audio_WaitForAudioStreamComplete(void){
return Semaphore_pend(audioSemaphoreHandle, BIOS_WAIT_FOREVER);
}
/* AudioPlayer task main loop */
void AudioTask_Main(UArg arg0, UArg arg1){
while(1){
if(Audio_WaitForAudioStreamComplete()){
/* In this function i'm reading audio data from external flash
and put it to the I2S transactions queue.
*/
AudioPlayer_Loop();
}
}
}
/* I2S driver WriteCallback */
static void I2SWriteCallback(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transaction){
/* Check if list is empty... */
/* ... */
// We must consider previous transaction as the current one is not over
I2S_Transaction* finished = (I2S_Transaction*)List_prev(&transaction->queueElement);
if(finished){
// Remove already processed transaction and put it to the list to get new audio data
List_remove(&toWriteAudioStream, (List_Elem*)finished);
finished->queueElement.prev = NULL;
finished->queueElement.next = NULL;
List_put(toReadFromFlashAudioStream, (List_Elem*)finished);
}
/* Check status for errors or I2S_ALL_TRANSACTIONS_SUCCESS */
/* ... */
/* Post semaphore to the AudioTask. */
AudioTask_Wakeup();
}
Function which triggers network join process.
/* Send Commisioning request to the stack. */
static void ZigbeeNetwork_JoinRequest(void){
zstack_bdbStartCommissioningReq_t startCommisioniongReq = {
.commissioning_mode = DEFAULT_COMISSIONING_MODE };
Zstackapi_bdbStartCommissioningReq(networkConfig.applicationTaskId, &startCommisioniongReq);
}This function is triggered after button is pressed.
I've done some measurements using logic analyzer. Here is what i noticed.
1. When this issue occures interval between I2SWriteCallback calls is too long (hence the melody sounds like noise).
You can see this below on the screenshot.
I'm transferring audio data with following settings:
sampling rate: 44.1kHz
word length: 16bit
speakers: mono
transaction buffer size: 256 samples
So the transfer of single buffer should take about 5.8ms, but as you can see above it varies from ~20ms to ~40ms.
Below you can see how it looks when everything is ok:
I've also checked how much time it takes from post the semaphore to the task's wakeup, but it looks good (tenths of microseconds).
I tried also to raise the priority of I2S hwi, but it didn't help.
I traced whole execution path from button press to the commisiong request message send, but didn't find anything that could cause this big interval between isr calls.
Audio Task is the highest priority so it shouldn't be preempted by any other task. I believe there is no HWI or SWI in the SDK which could be executed for over 20 ms.
I've also measured time to read data from external flash and it fits too (it's about 1 ms). Apart from that this works well, excluding this one case.
Now two strange things that i noticed.
1. When i change the semaphore timeout to be 150 ticks or less, then this issue doesn't occure.
I don't get how the sempahore's timeout could impact on I2S isr calls... Is it possible, that there is some bug in rtos?
/* Wait for semaphore posted from I2S write callback. */
bool Audio_WaitForAudioStreamComplete(void){
return Semaphore_pend(audioSemaphoreHandle, /*BIOS_WAIT_FOREVER*/ 100); // OK, no noise, but if timout is higher than 150 then it's not OK :<
}2. When the application is started from the debbuger this issue doesn't occure (even for BIOS_WAIT_FOREVER in Sempahote_pen() ).
I tried to get some info from graph analyzer tool, but as in debugging session everything is ok then on the charts also everything is ok.


I'm stuck with this. If anyone have some idea what else i could check please let me know.
Especially i'd like to know what is about this semaphore's timeout.
Best regards,
mf