This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Getting i2s to work...

Hi,

I'd like to output some audio data through i2s. It's quite easy to understand your examples provided on infocenter, however, I can't get my code to work.

Here is what I do:

#define TX_BUFFER_SIZE    8                /* Length of transmit buffer, specified in 32-bit words */
                                                  
static uint32_t   mTxBuffer[TX_BUFFER_SIZE];

//-------------------------------------------------------------------

void  soundInitialise (ASoundCompleteCallback pCB)
{
    nrf_drv_i2s_config_t  config = NRF_DRV_I2S_DEFAULT_CONFIG;

    nrf_drv_i2s_init    (&config, onTxPrepare);
    nrf_gpio_pin_clear  (SDMODE_PIN);
    nrf_gpio_cfg_output (SDMODE_PIN);
}


void  soundPlay ()
{
    nrf_gpio_pin_set  (SDMODE_PIN);

    nrf_drv_i2s_start (NULL, mTxBuffer, TX_BUFFER_SIZE, 0);
}


static void  onTxPrepare (uint32_t const *p_data_received,
                          uint32_t       *p_data_to_send,
                          uint16_t        number_of_words)
{
    if (p_data_received != NULL)
        ;

    if (p_data_to_send  != NULL)
    {
        if (mTuneTx >= mTuneStop)
        {
            nrf_drv_i2s_stop   ();
            nrf_gpio_pin_clear (SDMODE_PIN);

            return;
        }

        while (number_of_words)
        {
            if (mTuneTx < mTuneStop)
               *p_data_to_send = *mTuneTx;
            else
               *p_data_to_send = 0;

            number_of_words--;
            mTuneTx++;
        }
    }
}

As soon as I call soundPlay () the code jumps into onTxPrepare () where a HardFault exception occurs. Why?

Thanks for your assistance.

  • Have you debugged and stepped through onTxPrepare() to see exactly where in the handler function the code hard faults? Do you mind uploading all of you code?

  • Hi Martin,

    it crashes out in "*p_data_to_send = *mTuneTx". Used memcpy before - then changed it to this.

    Please find code attached...

    uisound.c

  • It's not easy to say what is going on here as it is not easy to reproduce on my end. I have tried to the best of my abilities to merge your code into the I2S example from the SDK. I'm able to get some code that compiles and runs fine, but I don't get any hard faults. My best guess is that your code is trying to access some "bad" memory in the while(number_of_words). And are you trying to copy the content of the mTuneTx buffer to p_data_to_send? Won't this code just overwrite the value in p_data_to_send[0] 'number_of_words' number of times since you are not incrementing p_data_to_send?

  • Hi Martin,

    Thanks for this and yes, you're correct about the increment++.

    The code still crashes but with a bit of luck I'll get it to work. Please confirm that my assumptions are correct:

    • The buffer in nrf_drv_i2s_start () (2nd parameter) is used internally by the i2s driver, i.e. by easy-DMA or something like this.
    • What I need to do for this is to allocate a buffer in RAM? It's size needs to be a multiple of 4 bytes?
    • If I only want to send audio data to a PCM amplifier I need to react to p_data_to_send != NULL. Is that so?
    • I then need to copy number_of_words from my sound file (which is in const-memory) to *p_data_to_send.
    • p_data_to_send points to the buffer provided in nrf_drv_i2s_start ()?
    • number_of_words are 32-bit words?
    • If my sound file is done I call nrf_drv_i2s_stop () from within the interrupt routine?

    Thank you M

  • Hi,

    I have tracked the issue a bit further. I find that p_i2s->CONFIG.TXEN = (p_buffer_tx != NULL) ? 1 : 0; (see line 494, nrf_i2s.h) may cause the problem. If set to 1 the code crashes, if set to 0 it doesn't. Crashing means: the code jumps to memory address 0x000007BC.

Related