This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2652R: I2S Callback interval is too long after pairing to the zigbee network.

Part Number: CC2652R
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 Slight smile

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

  • Hello mf,

    What is the node type of your Zigbee device, ZC/ZR/ZED?  There are two tasks in a Zigbee project, application and stack, which are set to a priority of 2 and 5, respectively.  As 15 would be the highest priority, have you set this to the value of your task accordingly?  Keep in mind that the radio HWI will remain a higher priority.  When you reset your device, does the Zigbee functionality resume its network or rejoin the existing one?  Have you considered using an event to further process your I2S information and more quickly exiting the callback?

    Regards,
    Ryan

  • Hi Ryan,

    Thanks for quick response.
    i'll answer you questions one by one.

    1. My device type is ZR.

    2. In my application i've more than two tasks. There're
    - stack task(prio 5)
    - application task (prio 2)
    - buttons task (prio 5)
    - audio task (prio 6)
    As you can see audio is highest priority.

    3. I was considering that radio could preempt I2S ISR, but i don't expect it could be exectued that long (or that called so often) to cause 20-40 ms delay in I2S ISR calls.

    4. I'm not sure what you exatctly mean here. After reset of the device, it rejoins existing network, which it was previously paired to.

    5. To be honest i wasn't. I can try this, but as you can see time between semaphore's post from ISR and Audio task wakeup is sufficient (mean 60 us). Apart of that, if this will resolve the problem it doesn't explain the strange behaviour with the semaphore.

    Regards,
    mf

  • Thank you for adequately answering all of my questions sequentially.  The ZR node is always on and does not have to maintain the joining of all nodes as with the ZC Trust Center.  If the Zigbee network traffic were the source of the problem then the device would continue experiencing issues after the reset and rejoin.  As it stands, your description implies that the I2S may interfere with the Zigbee join process in some way which could be affecting further operation, for example the radio continues to actively scan channels or search for open networks. Do you have Finding and Binding enabled, and does behavior change if you disable this feature?  Would it be possible to disable I2S while joining a network to observe whether this affects the occurrence of the problem?

    I spoke with a colleague who knows more about I2S Driver and they had the following to say: "I would recommend to verify whether the I2S clocks are output with the right frequency. I expect something wrong at this level as the I2S callbacks change frequency while remaining at a pretty stable frequency.
    Which device outputs the I2S clocks (i.e. which one is the master)?  In all the cases, the configuration of the driver may have been modified. If the TLV is the I2S master, verify the frequency of the clock inputted to it (MCLK) and if the settings sent over I2C are as expected."

    Would it be possible to migrate your solution to a newer SDK (SIMPLELINK-CC13XX-CC26XX-SDK) to confirm that there is not a bug at work which has already been resolved?  Or is it possible to recreate the issue by combining ZR and I2S example provided by TI?

    Regards,
    Ryan

  • Hi Ryan,

    sorry for late answer i was on a sick leave.

    I checked the I2S clocks, but seems to be no problem there.
    I did some workaround which helped, but to be honest i still don't know what was causing this issue.
    The workaround was to initialize the I2S driver just before start of the audio data transfer and close it just after the transfer ends.

    Regards,
    mf

  • It's good to hear from you again and I hope you are feeling better.

    I'm glad you've found a workaround.  I do not have enough experience with using Z-Stack and I2S to theorize other possible causes, furthermore I lack the resources to replicate and debug the issue.  Another solution based on what you've described, although likewise not optimal, would be to perform a software reset with SysCtrlSystemReset immediately after first joining the network.  This can be detected in the BDB_COMMISSIONING_NWK_STEERING case of zclSampleSw_ProcessCommissioningStatus for BDB_COMMISSIONING_SUCCESS.  It should only occur once, after which hopefully your audio will be uninterrupted. 

    Regards,
    Ryan