This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SDK 17 - NRF52840 - nrf_queue_write() asserts when buffer size > queue size

Hi everyone,

I use the function nrf_queue_write for queueing data. Also I use the NRF_QUEUE_MODE_OVERFLOW  mode to overwrite old data in case the queue is full.

My problem is that nrf_queue_write asserts when the buffer size is greater thant the queue size (see nrf_queue.c)

ret_code_t nrf_queue_write(nrf_queue_t const * p_queue,
                           void const        * p_data,
                           size_t              element_count)
{
    ret_code_t status = NRF_SUCCESS;

    ASSERT(p_queue != NULL);
    ASSERT(p_data != NULL);
    ASSERT(element_count <= p_queue->size);
    
.......
.......
.......

So when I declare a queue size of 4 and try to queue a buffer of 5 elements, nrf_queue_write asserts.

#define QUEUE_SIZE 4                                // 4 element queue

NRF_QUEUE_DEF(int16_t, m_sensor_data_queue, QUEUE_SIZE, NRF_QUEUE_MODE_OVERFLOW); 

int16_t data_in[] = {6000, 8000, -10000, -12000, -14000};
uint8_t data_in_size = sizeof(data_in) / sizeof(data_in[0]);

void my_sensors_buffer() {
  ret_code_t err_code;

  nrf_queue_write(&m_sensor_data_queue, data_in, data_in_size); // It asserts when data_in_size > QUEUE_SIZE 
  APP_ERROR_CHECK(err_code);

}

It seems that something I don't understand. How can I work this arround?

  • Thank you for your effort Einar!!

  • There are clearly some issues with the queue implementation when using nrf_queue_write() combined with NRF_QUEUE_MODE_OVERFLOW. Another issue (which may have the same root cause) can be seen by using a different length, where the total number of elements added by the two calls to nrf_queue_write() is one more than the queue length.

    See this code:

    #define QUEUE_SIZE 6
    NRF_QUEUE_DEF(uint32_t, m_sensor_data_queue, QUEUE_SIZE, NRF_QUEUE_MODE_OVERFLOW);
    
    static int16_t data_in[] = {10, 20, 30, 40};
    static int16_t data_in_2[] = {1, 2, 3};
    
    void my_sensors_buffer(int run_count)
    {
        ret_code_t err_code;
        int16_t data_out;
        size_t queued;
    
        for(int run = 0; run < run_count; run++)
        {
            NRF_LOG_INFO("Queue some data, run %i", run);
    
            queued = nrf_queue_utilization_get(&m_sensor_data_queue);
            NRF_LOG_INFO("Queued before first write: %i", queued);
    
            err_code = nrf_queue_write(&m_sensor_data_queue, data_in, ARRAY_SIZE(data_in));
            APP_ERROR_CHECK(err_code);
    
            queued = nrf_queue_utilization_get(&m_sensor_data_queue);
            NRF_LOG_INFO("Queued before second write: %i", queued);
    
            err_code = nrf_queue_write(&m_sensor_data_queue, data_in_2, ARRAY_SIZE(data_in_2));
            APP_ERROR_CHECK(err_code);
    
            queued = nrf_queue_utilization_get(&m_sensor_data_queue);
            NRF_LOG_INFO("Queued after both writes: %i", queued);
    
            for (uint16_t i = 0; i < QUEUE_SIZE; i++)
            {
                err_code = nrf_queue_pop(&m_sensor_data_queue, &data_out);
                APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("Pop[%d] %d", run, data_out);
            }
    
            nrf_delay_ms(100); // Delay a bit to have time to output logs..
        }
    }
    

    Which gives this output:

    <info> app: Queue some data, run 0
    <info> app: Queued before first write: 0
    <info> app: Queued before second write: 4
    <info> app: Queued after both writes: 0
    <error> app: ERROR 5 [NRF_ERROR_NOT_FOUND] at C:\Users\eith\SDK\nRF5_SDK_17.1.0_ddde560\examples\other_projects\nrf_queue_test_279738\main.c:46
    PC at: 0x0002D02D
    <error> app: End of error report

    Note that the queue utilization after the first write is 4, as expected, but after the second write it is 0, and not 6 which it should have been (where one element should have been discarded).

    I have not got to the bottom of this, but for now I suggest using nrf_queue_push() instead. Then you could for instance replace:

            err_code = nrf_queue_write(&m_sensor_data_queue, data_in, ARRAY_SIZE(data_in));
            APP_ERROR_CHECK(err_code);

    with:

            for (uint16_t i = 0; i < ARRAY_SIZE(data_in); i++)
            {
                err_code = nrf_queue_push(&m_sensor_data_queue, &data_in[i]);
                APP_ERROR_CHECK(err_code);
            }

    This is an effective workaround of all issues I have seen.

  • Hi Einar,

    Thank you for your effort, I've just confirmed that nrf_queue_push() works flawlessly combined with NRF_QUEUE_MODE_OVERFLOW mode. I will go ahead with this approach.

    Do you know if these bugs are fixed by the development team in NRF connect SDK?

    Nick

  • Hi Nick,

    The nRF Connect SDK has a completely different architecture and use Zephyr queues (FIFO would be equivalent ish).

Related