BF706-EZMINI - Cannot run UART0 RX interrupt while SPORT 0 DMA is running ?

I have no idea why, but even with the both interrupts turned on for the USART 0 Bi-directional and SPORT 0 RX I can only  fire one but not the other...Is it possible to get both to execute ? I'm not running USART 0 on DMA, only with the built in interrupt. Seems the DMA Interrupts for the SPORT 0 RX take precedence over the UART. As you can see in the code below when I shut off the SPORT DMA's inside the handler, then the UART 0 Bi-directional interrupts kick in again...This is quite strange since the UART interrupts should run unaffected by the SPORT perhipheral ? Can this work simultaneously, both UART and SPORT(s) interrupts ?

// Function disable_SPORT disables SPORT first and then DMA
void disable_SPORT(void)
{
*pREG_SPORT0_CTL_B &= ~1;
*pREG_SPORT0_CTL_A &= ~1;
__builtin_ssync();

*pREG_DMA0_CFG &= ~ENUM_DMA_CFG_EN;
*pREG_DMA1_CFG &= ~ENUM_DMA_CFG_EN;
__builtin_ssync();
}

// Function SPORT0_RX_interrupt_handler is called after a complete
// frame of input data has been received.
void SPORT0_RX_interrupt_handler(uint32_t iid, void *handlerArg)
{

audio_buffer[0] = SP0B_buffer[0] << 8;
audio_buffer[1] = SP0B_buffer[1] << 8;

//audio_processing(audio_buffer, 2);

SP0A_buffer[0] = audio_buffer[0] >> 8;
SP0A_buffer[1] = audio_buffer[1] >> 8;

//*pREG_UART0_IMSK_SET=0x0001;
disable_SPORT();
}

  • I'm going to answer my own question here...After further investigation I have found the obvious! Firstly I have shut off the branch prediction enable by keeping it clear instead of set just in case...That did absolutely nothing like I expected...In fact I should probably turn it back on. The issue is that the interrupts are nested and the fastest occurring interrupt will pre-empt the other. I got around the issue by turning the fast interrupt off and re-enabling it later after the UART interrupt has some time to breathe. If no UART processing is involved, the UART returns in a speedy manner and turns the SPORT 0 interrupt back on. I have not seen an example of how else to accomplish this more efficiently. It is a known fact that DMA will take over and has to be stopped for a while to allow other interrupts to occur even on other DMA channels. It works fine for now! 

    // Configure SYSCFG.
    R1 = SYSCFG;

    R0 = ( BITM_SYSCFG_CCEN | // Enable the cycle counter.
    BITM_SYSCFG_SNEN | // Enable self-nesting interrupts.
    //BITM_SYSCFG_BPEN | // Enable branch prediction.
    BITM_SYSCFG_MPWEN ); // Enable MMR posted writes.
    R1 = R0 | R1;

    SYSCFG = R1;

    Code above does nothing on latest BF706, so probably best to leave Branch Prediction On at all times, since it does not interfere...

    // Function SPORT0_RX_interrupt_handler is called after a complete
    // frame of input data has been received.
    void SPORT0_RX_interrupt_handler(uint32_t iid, void *handlerArg)
    {

    audio_buffer[0] = SP0B_buffer[0] << 8;
    audio_buffer[1] = SP0B_buffer[1] << 8;

    if (gbFilterOn == true)
    audio_processing(audio_buffer, 2);

    SP0A_buffer[0] = audio_buffer[0] >> 8;
    SP0A_buffer[1] = audio_buffer[1] >> 8;

    adi_int_UninstallHandler(iid);        <=== Shut off this very DMA Interrupt after the last buffer transfer to codec...
    }

    Now here is the punch line...Re-enable Sport 0 interrupt after the UART interrupt had a chance to quite possibly engage...i.e.

    ...

    ...

    WelcomeMessage();

    // Only pBlinker exit signal can break out of the super loop!

    while (pBlinker->Exit == false)
    {
    //disable_SPORT();
    UART_Command_Processor();

    if (pBlinker->AudioOn == true || pBlinker->FilterOn == true)
    restart_interrupts();
    }

    return 0;

    ...

    ...

    This breaks down to the following simple interrupt re-enable...Which is as easy as re-registering the handler according to ADI source...

    void restart_interrupts(void)
    {
    // Set SPORT0_B DMA interrupt handler
    adi_int_InstallHandler(INTR_SPORT0_B_DMA, SPORT0_RX_interrupt_handler, 0, true);

    }

    That's it! There may be a better way to do this that is a couple flags, But this does work quite fast! If you want to understand how to make this work efficiently check out my tutorial on Audio Terminal Control for the BF706! Cheers...