Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Help me understand the operation of the NRF_RINGBUF module

Hi!

I'm trying to figure out the nrf_ringbuf module, and would really appreciate some advice about its intended use case. The api exposes the following functions:


void 	nrf_ringbuf_init (nrf_ringbuf_t const *p_ringbuf)
 
ret_code_t 	nrf_ringbuf_alloc (nrf_ringbuf_t const *p_ringbuf, uint8_t **pp_data, size_t *p_length, bool start)
 
ret_code_t 	nrf_ringbuf_put (nrf_ringbuf_t const *p_ringbuf, size_t length)
 
ret_code_t 	nrf_ringbuf_cpy_put (nrf_ringbuf_t const *p_ringbuf, uint8_t const *p_data, size_t *p_length)
 
ret_code_t 	nrf_ringbuf_get (nrf_ringbuf_t const *p_ringbuf, uint8_t **pp_data, size_t *p_length, bool start)
 
ret_code_t 	nrf_ringbuf_free (nrf_ringbuf_t const *p_ringbuf, size_t length)
 
ret_code_t 	nrf_ringbuf_cpy_get (nrf_ringbuf_t const *p_ringbuf, uint8_t *p_data, size_t *p_length)


This is my current flow of execution:

Ask for space with nrf_ringbuffer_alloc( p_ringbuf, pp_data, p_length, false). This gives me a pointer to where I can write the amount of bytes that I've requested.

Write bytes to the allocated pointer location using memcpy( pp_data, inputBuffer, length )

Commit the bytes to the ring buffer using nrf_ringbuf_put( p_ringbuf, length)

...

Later pop things from the ring buffer using:

nrf_ringbuf_get ( p_ringbuf, pp_data, &length, false );

memcpy( inputBuffer, pp_data, length );

nrf_ringbuf_free( p_ringbuf, length );

However, I am getting an error, NRF_ERROR_INVALID_STATE, from line 94 of nrf_ringbuf.c:

 if (nrf_atomic_u32_fetch_sub(&p_ringbuf->p_cb->flag, 1 << WR_OFFSET) & (1 << WR_OFFSET))

I believe I am not using the api correctly, as I haven't understood the use case of nrf_ringbuf_cpy_put() and cpy_get() . Are these supposed to be called in-between alloc & put, and get & free? It is not very clear in the documentation. Please advise.


Cheers and all the best,
Rares Gosman

Parents
  • Hi Hakon,

    Thanks for the advice. I updated to SDK14.2 and kept running into the same issue. I realized it was a problem with the nrf_ringbuf_cpy_get() function. The syntax being used with memcpy() is incorrect. It is provided like so in the SDK:

        if (length > trail)
        {
            memcpy(&p_ringbuf->p_buffer[masked_rd_idx], p_data, trail);
            length -= trail;
            masked_rd_idx = 0;
            p_data += trail;
        }
        memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], length);
        p_ringbuf->p_cb->rd_idx += *p_length;


    Since this is a get() function, it should be filling the user-provided p_data buffer with data from the ring buffer. However, in this section of the code, where it handles the wrap-around behavior, the first memcpy() call is copying blank data from p_data into the ring buffer, and overwriting valid data. Line 212 of "nrf_ringbuf.c" should be:

    memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], trail);

    On the other hand, the nrf_ringbuf_cpy_put() command is fine:

        if (length > trail)
        {
            memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, trail);
            length -= trail;
            masked_wr_idx = 0;
            p_data += trail;
        }
        memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, length);
        p_ringbuf->p_cb->wr_idx += *p_length;

    Notice that both memcpy() calls are being executed with the same order of parameters, since the destination is the ring buffer in the event of a put() command.

    Please notify those in charge of this section of the SDK of this error.

    Cheers,
    Rares Gosman 

Reply
  • Hi Hakon,

    Thanks for the advice. I updated to SDK14.2 and kept running into the same issue. I realized it was a problem with the nrf_ringbuf_cpy_get() function. The syntax being used with memcpy() is incorrect. It is provided like so in the SDK:

        if (length > trail)
        {
            memcpy(&p_ringbuf->p_buffer[masked_rd_idx], p_data, trail);
            length -= trail;
            masked_rd_idx = 0;
            p_data += trail;
        }
        memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], length);
        p_ringbuf->p_cb->rd_idx += *p_length;


    Since this is a get() function, it should be filling the user-provided p_data buffer with data from the ring buffer. However, in this section of the code, where it handles the wrap-around behavior, the first memcpy() call is copying blank data from p_data into the ring buffer, and overwriting valid data. Line 212 of "nrf_ringbuf.c" should be:

    memcpy(p_data, &p_ringbuf->p_buffer[masked_rd_idx], trail);

    On the other hand, the nrf_ringbuf_cpy_put() command is fine:

        if (length > trail)
        {
            memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, trail);
            length -= trail;
            masked_wr_idx = 0;
            p_data += trail;
        }
        memcpy(&p_ringbuf->p_buffer[masked_wr_idx], p_data, length);
        p_ringbuf->p_cb->wr_idx += *p_length;

    Notice that both memcpy() calls are being executed with the same order of parameters, since the destination is the ring buffer in the event of a put() command.

    Please notify those in charge of this section of the SDK of this error.

    Cheers,
    Rares Gosman 

Children
No Data
Related