Flavio Andrade
Flavio Andrade

Reputation: 131

How to wrap around a ring buffer?

I am trying to implement a ring buffer in C to an external flash memory. For reference the flash memory is BR24G32-3 with 4kb.

I am having difficulties when it comes to the wrap around. After writing to all addresses 0x0000 ~ 0x1000, when it comes to wrap around and writes over the oldest data, my checking causes an infinite loop.

What I see my algorithm doing:

How can I improve this algorithm? I am looking to fix the error when I finish writing to the end address 0x1000 and when I reset to 0x0000, my ring buffer is already finding WRITTEN (0x31) flag at every block of data.

Thank you in advance.

void rb_write_to_flash(ring_buffer_t *rb)
{
    uint8_t base_head_address[2] = {0x01, 0x0C};
    ringbuf_head_position(head_position); // Load initial state of the ring buffer

    if (head_position[0] == 0xFF && head_position[1] == 0xFF)
    {
        NRF_LOG_INFO("HEAD == 0xFF");
        head_position[0] = 0x00;
        head_position[1] = 0x00;
    }

    // Convert head_position to a uint16_t value
    uint16_t head_pos_value = ((uint16_t)head_position[0] << 8) | head_position[1];

    do
    {
        // Check if position has been written
        nrf_drv_twi_tx(&m_twi, EEPROM_ADDRESS, head_position, 2, true);
        nrf_drv_twi_rx(&m_twi, EEPROM_ADDRESS, head_buffer, sizeof(head_buffer));

        if (head_buffer[28] == WRITTEN)
        {
            NRF_LOG_INFO("HEAD ALREADY WRITTEN");

            // Increment position by 0x20
            head_pos_value += 0x20;
            if (head_pos_value >= 0x1000) // Checking for overflow
            {
                NRF_LOG_INFO("WRAPPING AROUND");
                head_pos_value = 0x00; // Reset if it exceeds 0xFFFF
                uint8_t initial_address[2] = {0x00, 0x00};
                write_record(base_head_address, initial_address, 2);

                // Clear the WRITTEN flag for the first position in EEPROM
                uint8_t clear_buffer[30] = {0xFF}; // Assuming 0xFF is the default/empty state
                write_record(initial_address, clear_buffer, sizeof(clear_buffer));
            }

            NRF_LOG_INFO("HEAD POSITION: 0x%04x", head_pos_value);

            // Convert back to array
            head_position[0] = (head_pos_value >> 8) & 0xFF;
            head_position[1] = head_pos_value & 0xFF;
        }

    } while (head_buffer[28] == WRITTEN);

    // Write data to the correct position
    rb->buffer[0].written = WRITTEN; // Set flag as written
    write_record(head_position, (uint8_t *)rb->buffer, sizeof(rb->buffer));

    // Write the new head position to flash memory
    write_record(base_head_address, head_position, 2);
}

Upvotes: 1

Views: 259

Answers (0)

Related Questions