Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Sending I2S data via BLE using queue

Hi,

I am writing an application that reads data from the I2S interface, adds it to a queue and sends it via BLE (the code I have implemented so far is added at the end of this post).

In a previous thread (https://devzone.nordicsemi.com/f/nordic-q-a/87656/create-custom-event-to-trigger-updating-data-in-gatt-table), I have reached a state where I am able to send arbitrary data via BLE. I also know that reading data from the I2S works. However, integrating those parts into one application causes the application to run into an error (all 4 LEDs on my nRF52 DK are on).

EDIT: For clarification: the nRF is advertising and I can connect to it from nRF Connect for Desktop and Mobile. The problem starts when I enable notifications and the code, thereby, enters the if-clause in line 46 in my main function (i2s_transfer becomes true).

The code is based on the ble_app_template and the I2S loopback example. I'm using the nRF52 DK, nRF5 SDK 17.1.0 with S132 and Segger emStudio 5.42a.

Could there be too many interrupts that call the data_handler so that the rest of the code cannot be executed (I'm sampling with ~ 44 kHz, so the buffer of 256 bytes will be filled quickly)? I'm also thinking that the allocated RAM could be insufficient (I attach my section placement macros below).

Can anybody suggest a fix that I can try or an alternative implementation to achieve what I have mentioned above? Any help is appreciated.

CODE:

The section placement macros:

FLASH_PH_START=0x0
FLASH_PH_SIZE=0x80000
RAM_PH_START=0x20000000
RAM_PH_SIZE=0x10000
FLASH_START=0x26000
FLASH_SIZE=0x5a000
RAM_START=0x20002ad8
RAM_SIZE=0xd528

Here are the relevant declarations:

#define I2S_DATA_BLOCK_WORDS    256

static uint32_t m_buffer_rx[2][I2S_DATA_BLOCK_WORDS];
static uint32_t m_buffer_tx[2][I2S_DATA_BLOCK_WORDS];

NRF_QUEUE_DEF(uint8_t, m_queue, 3072, NRF_QUEUE_MODE_OVERFLOW);

uint8_t m_array[244] = {0};

Here is my main function:

/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds;
    uint8_t err_code;

    // Initialize.
    log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    power_management_init();

    // Initialize TWI/ I2C & Setup ADC
    twi_adc_configuration();

    // Initialize i2s
    err_code = i2s_init();
    if (err_code == NRF_SUCCESS)
    {
        NRF_LOG_INFO("I2S successfully initialized.");
    }
    else
    {
        NRF_LOG_INFO("Error initializing I2S.");
    }

    // Initialize BLE
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    peer_manager_init();

    // Start execution.
    NRF_LOG_INFO("Template example started.");

    // Start advertising
    advertising_start(erase_bonds);

    // Enter main loop.
    for (;;)
    {
        if (i2s_transfer) 
        {
            // start i2s
            err_code = start_i2s();
            if (err_code == NRF_SUCCESS) 
            {
                NRF_LOG_INFO("I2S started");
            }
            else
            {
                NRF_LOG_INFO("Failed starting I2S");
            }

            if (nrf_queue_utilization_get(&m_queue) >= 244)
            {
                // get data from the queue
                err_code = nrf_queue_read(&m_queue, &m_array, sizeof(m_array));
                if ((err_code != NRF_SUCCESS) &&
                        (err_code != NRF_ERROR_INVALID_STATE) &&
                        (err_code != NRF_ERROR_RESOURCES) &&
                        (err_code != NRF_ERROR_BUSY) &&
                        (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                       )
                {
                    APP_ERROR_CHECK(err_code);
                }

                // send data via BLE
                err_code = ble_aas_value_update(&m_aas, &m_array);
                if ((err_code != NRF_SUCCESS) &&
                    (err_code != NRF_ERROR_INVALID_STATE) &&
                    (err_code != NRF_ERROR_RESOURCES) &&
                    (err_code != NRF_ERROR_BUSY) &&
                    (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                   )
                {
                    APP_ERROR_CHECK(err_code);
                }

                if (err_code == NRF_ERROR_RESOURCES)
                {
                    NRF_LOG_DEBUG("error resources");
                    if (ble_ready != true)
                    {
                        idle_state_handle();
                    }
                    ble_ready = false;
                }
            }
        }
    }   
     
    nrf_drv_i2s_stop();

    NRF_LOG_FLUSH();

    bsp_board_leds_off();
}

My start_i2s function:

int start_i2s()
{
    uint32_t err_code = NRF_SUCCESS;

    nrf_drv_i2s_buffers_t const initial_buffers = {
        .p_tx_buffer = NULL,
        .p_rx_buffer = m_buffer_rx[0],
    };

    err_code = nrf_drv_i2s_start(&initial_buffers, I2S_DATA_BLOCK_WORDS, 0);
    APP_ERROR_CHECK(err_code);

    return err_code;
}

and my data handler:

static void data_handler(nrf_drv_i2s_buffers_t const * p_released,
                         uint32_t                      status)
{
    // 'nrf_drv_i2s_next_buffers_set' is called directly from the handler
    // each time next buffers are requested, so data corruption is not
    // expected.
    ASSERT(p_released);

    // When the handler is called after the transfer has been stopped
    // (no next buffers are needed, only the used buffers are to be
    // released), there is nothing to do.
    if (!(status & NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED))
    {
        return;
    }

    // First call of this handler occurs right after the transfer is started.
    // No data has been transferred yet at this point, so there is nothing to
    // check. Only the buffers for the next part of the transfer should be
    // provided.
    if (!p_released->p_rx_buffer)
    {
        // .p_tx_buffer = m_buffer_tx[1] changed to .p_tx_buffer = NULL, since we only receive data
        nrf_drv_i2s_buffers_t const next_buffers = {
            .p_rx_buffer = m_buffer_rx[1],
            .p_tx_buffer = NULL,
        };
        APP_ERROR_CHECK(nrf_drv_i2s_next_buffers_set(&next_buffers));

    }
    else
    {
        uint16_t i;
        uint32_t const * p_word = NULL;
        uint8_t sample[3];

        for (i = 0; i < I2S_DATA_BLOCK_WORDS; ++i)
        {
            p_word = &mp_block_to_check[i];
            //decompose 32-bit sample and discard msb
            sample[0] = ((uint8_t const *)p_word)[0];
            sample[1] = ((uint8_t const *)p_word)[1];
            sample[2] = ((uint8_t const *)p_word)[2];
            printf("\n %2x%2x%2x", sample[0], sample[1], sample[2]);

            // copy data to the queue
            ret_code_t err_code;
            err_code = nrf_queue_write(&m_queue, &sample, sizeof(sample));
            NRF_LOG_DEBUG("data added to queue.");
        }
       
        // The driver has just finished accessing the buffers pointed by
        // 'p_released'. They can be used for the next part of the transfer
        // that will be scheduled now.
        APP_ERROR_CHECK(nrf_drv_i2s_next_buffers_set(p_released));

    }
}

Parents
  • Hello,

     Could you please debug into the preprocessor symbols and check the log to see where the error is?  You can send the log to us. 

    Thanks.

    Best Regards,

    Kazi Afroza Sultana

  • Hi,

    I found the option to Build -> Show Build Log in Segger emStudio. I'm posting the content of the log below. Is that what you were asking for? Did you also see my update below? Could you provide any hints how to solve this?

    Building 'ble_app_template_pca10040_s132' from solution 'ble_app_template_pca10040_s132' in configuration 'Debug'
    1> Assembling 'thumb_crt0.s'
    2> Compiling 'nrf_log_backend_rtt.c'
    1> Compiling 'nrf_log_backend_serial.c'
    1> Compiling 'nrf_log_backend_uart.c'
    2> Compiling 'nrf_log_default_backends.c'
    2> Compiling 'nrf_log_frontend.c'
    1> Compiling 'nrf_log_str_formatter.c'
    1> Compiling 'app_button.c'
    2> Compiling 'app_error.c'
    1> Compiling 'app_error_handler_gcc.c'
    2> Compiling 'app_error_weak.c'
    1> Compiling 'app_scheduler.c'
    1> Compiling 'app_timer2.c'
    1> Compiling 'app_util_platform.c'
    2> Compiling 'crc16.c'
    1> Compiling 'drv_rtc.c'
    1> Compiling 'fds.c'
    2> Compiling 'hardfault_implementation.c'
    1> Compiling 'nrf_assert.c'
    2> Compiling 'nrf_atfifo.c'
    2> Compiling 'nrf_atflags.c'
    2> Compiling 'nrf_atomic.c'
    2> Compiling 'nrf_balloc.c'
    1> Compiling 'nrf_fprintf.c'
    2> Compiling 'nrf_fprintf_format.c'
    2> Compiling 'nrf_fstorage.c'
    2> Compiling 'nrf_fstorage_sd.c'
    1> Compiling 'nrf_memobj.c'
    1> Compiling 'nrf_pwr_mgmt.c'
    1> Compiling 'nrf_ringbuf.c'
    1> Compiling 'nrf_section_iter.c'
    2> Compiling 'nrf_sortlist.c'
    1> Compiling 'nrf_strerror.c'
    2> Compiling 'sensorsim.c'
    2> Compiling 'nrf_queue.c'
    2> Assembling 'ses_startup_nrf52.s'
    2> Assembling 'ses_startup_nrf_common.s'
    1> Compiling 'system_nrf52.c'
    2> Compiling 'boards.c'
    1> Compiling 'nrf_drv_clock.c'
    2> Compiling 'nrf_drv_uart.c'
    2> Compiling 'nrfx_atomic.c'
    1> Compiling 'nrfx_clock.c'
    2> Compiling 'nrfx_gpiote.c'
    1> Compiling 'nrfx_prs.c'
    1> Compiling 'nrfx_uart.c'
    1> Compiling 'nrfx_uarte.c'
    1> Compiling 'nrfx_i2s.c'
    2> Compiling 'nrfx_twi.c'
    1> Compiling 'nrf_drv_twi.c'
    2> Compiling 'bsp.c'
    2> Compiling 'bsp_btn_ble.c'
    1> Compiling 'main.c'
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c: In function ‘notification_timeout_handler’:
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:266:45: warning: passing argument 2 of ‘ble_aas_value_update’ from incompatible pointer type [-Wincompatible-pointer-types]
    1> In file included from /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:94:
    1> ./ble_aas.h:99:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘uint8_t (*)[244]’ {aka ‘unsigned char (*)[244]’}
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c: In function ‘main’:
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:1067:53: warning: passing argument 2 of ‘ble_aas_value_update’ from incompatible pointer type [-Wincompatible-pointer-types]
    1> In file included from /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:94:
    1> ./ble_aas.h:99:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘uint8_t (*)[244]’ {aka ‘unsigned char (*)[244]’}
    1> Compiling 'ble_aas.c'
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/pca10040/s132/ses/ble_aas.c: In function ‘on_write’:
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/pca10040/s132/ses/ble_aas.c:134:43: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
    1> Compiling 'utils.c'
    2> Compiling 'SEGGER_RTT.c'
    1> Compiling 'SEGGER_RTT_Syscalls_SES.c'
    2> Compiling 'SEGGER_RTT_printf.c'
    1> Compiling 'auth_status_tracker.c'
    1> Compiling 'ble_advdata.c'
    2> Compiling 'ble_advertising.c'
    2> Compiling 'ble_conn_params.c'
    1> Compiling 'ble_conn_state.c'
    2> Compiling 'ble_srv_common.c'
    2> Compiling 'gatt_cache_manager.c'
    2> Compiling 'gatts_cache_manager.c'
    2> Compiling 'id_manager.c'
    1> Compiling 'nrf_ble_gatt.c'
    1> Compiling 'nrf_ble_qwr.c'
    1> Compiling 'peer_data_storage.c'
    1> Compiling 'peer_database.c'
    2> Compiling 'peer_id.c'
    2> Compiling 'peer_manager.c'
    2> Compiling 'peer_manager_handler.c'
    1> Compiling 'pm_buffer.c'
    1> Compiling 'security_dispatcher.c'
    1> Compiling 'security_manager.c'
    2> Compiling 'utf.c'
    1> Compiling 'nrf_sdh.c'
    1> Compiling 'nrf_sdh_ble.c'
    2> Compiling 'nrf_sdh_soc.c'
    1> Generating linker script 'ble_app_template_pca10040_s132.ld'
    1> Linking ble_app_template_pca10040_s132.elf
    Build complete
    

Reply
  • Hi,

    I found the option to Build -> Show Build Log in Segger emStudio. I'm posting the content of the log below. Is that what you were asking for? Did you also see my update below? Could you provide any hints how to solve this?

    Building 'ble_app_template_pca10040_s132' from solution 'ble_app_template_pca10040_s132' in configuration 'Debug'
    1> Assembling 'thumb_crt0.s'
    2> Compiling 'nrf_log_backend_rtt.c'
    1> Compiling 'nrf_log_backend_serial.c'
    1> Compiling 'nrf_log_backend_uart.c'
    2> Compiling 'nrf_log_default_backends.c'
    2> Compiling 'nrf_log_frontend.c'
    1> Compiling 'nrf_log_str_formatter.c'
    1> Compiling 'app_button.c'
    2> Compiling 'app_error.c'
    1> Compiling 'app_error_handler_gcc.c'
    2> Compiling 'app_error_weak.c'
    1> Compiling 'app_scheduler.c'
    1> Compiling 'app_timer2.c'
    1> Compiling 'app_util_platform.c'
    2> Compiling 'crc16.c'
    1> Compiling 'drv_rtc.c'
    1> Compiling 'fds.c'
    2> Compiling 'hardfault_implementation.c'
    1> Compiling 'nrf_assert.c'
    2> Compiling 'nrf_atfifo.c'
    2> Compiling 'nrf_atflags.c'
    2> Compiling 'nrf_atomic.c'
    2> Compiling 'nrf_balloc.c'
    1> Compiling 'nrf_fprintf.c'
    2> Compiling 'nrf_fprintf_format.c'
    2> Compiling 'nrf_fstorage.c'
    2> Compiling 'nrf_fstorage_sd.c'
    1> Compiling 'nrf_memobj.c'
    1> Compiling 'nrf_pwr_mgmt.c'
    1> Compiling 'nrf_ringbuf.c'
    1> Compiling 'nrf_section_iter.c'
    2> Compiling 'nrf_sortlist.c'
    1> Compiling 'nrf_strerror.c'
    2> Compiling 'sensorsim.c'
    2> Compiling 'nrf_queue.c'
    2> Assembling 'ses_startup_nrf52.s'
    2> Assembling 'ses_startup_nrf_common.s'
    1> Compiling 'system_nrf52.c'
    2> Compiling 'boards.c'
    1> Compiling 'nrf_drv_clock.c'
    2> Compiling 'nrf_drv_uart.c'
    2> Compiling 'nrfx_atomic.c'
    1> Compiling 'nrfx_clock.c'
    2> Compiling 'nrfx_gpiote.c'
    1> Compiling 'nrfx_prs.c'
    1> Compiling 'nrfx_uart.c'
    1> Compiling 'nrfx_uarte.c'
    1> Compiling 'nrfx_i2s.c'
    2> Compiling 'nrfx_twi.c'
    1> Compiling 'nrf_drv_twi.c'
    2> Compiling 'bsp.c'
    2> Compiling 'bsp_btn_ble.c'
    1> Compiling 'main.c'
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c: In function ‘notification_timeout_handler’:
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:266:45: warning: passing argument 2 of ‘ble_aas_value_update’ from incompatible pointer type [-Wincompatible-pointer-types]
    1> In file included from /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:94:
    1> ./ble_aas.h:99:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘uint8_t (*)[244]’ {aka ‘unsigned char (*)[244]’}
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c: In function ‘main’:
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:1067:53: warning: passing argument 2 of ‘ble_aas_value_update’ from incompatible pointer type [-Wincompatible-pointer-types]
    1> In file included from /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/main.c:94:
    1> ./ble_aas.h:99:60: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘uint8_t (*)[244]’ {aka ‘unsigned char (*)[244]’}
    1> Compiling 'ble_aas.c'
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/pca10040/s132/ses/ble_aas.c: In function ‘on_write’:
    1> /home/engineer/nRF-Dev/nRF5_SDK_17.1.0_ddde560/examples/ble_peripheral/surag_sense/pca10040/s132/ses/ble_aas.c:134:43: warning: initialization discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
    1> Compiling 'utils.c'
    2> Compiling 'SEGGER_RTT.c'
    1> Compiling 'SEGGER_RTT_Syscalls_SES.c'
    2> Compiling 'SEGGER_RTT_printf.c'
    1> Compiling 'auth_status_tracker.c'
    1> Compiling 'ble_advdata.c'
    2> Compiling 'ble_advertising.c'
    2> Compiling 'ble_conn_params.c'
    1> Compiling 'ble_conn_state.c'
    2> Compiling 'ble_srv_common.c'
    2> Compiling 'gatt_cache_manager.c'
    2> Compiling 'gatts_cache_manager.c'
    2> Compiling 'id_manager.c'
    1> Compiling 'nrf_ble_gatt.c'
    1> Compiling 'nrf_ble_qwr.c'
    1> Compiling 'peer_data_storage.c'
    1> Compiling 'peer_database.c'
    2> Compiling 'peer_id.c'
    2> Compiling 'peer_manager.c'
    2> Compiling 'peer_manager_handler.c'
    1> Compiling 'pm_buffer.c'
    1> Compiling 'security_dispatcher.c'
    1> Compiling 'security_manager.c'
    2> Compiling 'utf.c'
    1> Compiling 'nrf_sdh.c'
    1> Compiling 'nrf_sdh_ble.c'
    2> Compiling 'nrf_sdh_soc.c'
    1> Generating linker script 'ble_app_template_pca10040_s132.ld'
    1> Linking ble_app_template_pca10040_s132.elf
    Build complete
    

Children
No Data
Related