Skip to content

TwoWire library crashes, when quantity parameter in request_from() function is greater than SERIAL_BUFFER_SIZE. #858

@dac1e

Description

@dac1e

Operating System

Windows 11

IDE version

Arduino 2.3.5

Board

XIAO nRF52840

BSP version

Seed nRF52 Boards 1.1.12

Sketch

/*
AT24eeprom - Arduino libary for driving the AT24 I2 based eeproms Copyright (c)
2025 Wolfgang Schmieder. All right reserved.

Contributors:

  • Wolfgang Schmieder

Project home: https://github.com/dac1e/AT24eeprom/

This library is free software; you can redistribute it and/or modify it
the terms of the GNU Lesser General Public License as under published
by the Free Software Foundation; either version 3.0 of the License,
or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

/**

  • Note: The main purpose of this sketch is to reproduce a bug in the nRF52840 TwoWire driver.
    */

#include "Arduino.h"

#include <Wire.h>
#include "AT24CxEeprom.h"

#if defined SIZE_MAX
static size_t sizeMax() {return SIZE_MAX;}
#else
#include
static size_t sizeMax() {return std::numeric_limits<size_t>::max();}
#endif

class MYAT24C512 : public AT24C512 {
public:
MYAT24C512(TwoWire &wire, uint8_t deviceAddress) : AT24C512(wire, deviceAddress) {
}
private:
// We override this function so that read quantity is not artificially limited.
// Hence the TwoWire driver has to take care, that there is no read buffer
// overrun.
virtual size_t maxBulkReadQuantity() const override {
return sizeMax();
}
};

static MYAT24C512 eeprom(Wire, 0);

static typeof(Serial)& output = Serial;
//static typeof(Serial1)& output = Serial1;

static void fillBuffer(uint8_t* buffer, size_t bytesCount, uint8_t pattern) {
for(size_t i=0; i< bytesCount; i++) {
buffer[i] = pattern;
}
}

static bool writeReadAndCompare(size_t bytesCount, uint8_t pattern, uint16_t eepromAddress) {
uint8_t* writeBuffer = new uint8_t [bytesCount];

fillBuffer(writeBuffer, bytesCount, pattern);
eeprom.write(eepromAddress, writeBuffer , bytesCount);

delay(1);

uint8_t* readBuffer = new uint8_t [bytesCount];
eeprom.read(eepromAddress,readBuffer, bytesCount);

const bool result = (memcmp(readBuffer, writeBuffer, bytesCount) == 0);

delete[] readBuffer;
delete[] writeBuffer;

return result;
}

static void testWriteRead(uint8_t pattern) {
const size_t count = eeprom.pageSize();
const uint16_t eepromAddress = 0x08;

output.print("Write and read ");
output.print(count);
output.print(" times pattern ");
output.print(pattern, HEX);
output.print(" at address ");
output.print(eepromAddress, HEX);
output.print(" ... ");

// Write to and read back from eeprom adress
const bool bOk = writeReadAndCompare(eeprom.pageSize(), pattern, eepromAddress);

if(bOk) {
output.println(" Pass!");
} else {
output.println(" Fail!");
}
}

static size_t constexpr LOOPS = 3;
static size_t nRemainingLoops = LOOPS;

//The setup function is called once at startup of the sketch
void setup()
{
output.begin(115200);
output.println();
output.println("Starting write/read test.");
eeprom.begin();
}

// The loop function is called in an endless loop
void loop()
{
delay(3000);
if(nRemainingLoops) {
--nRemainingLoops;
output.println();
output.print("Executing test loop #");
output.println(LOOPS - nRemainingLoops);
testWriteRead(0x55);
testWriteRead(0xAA);
if(not nRemainingLoops) {
output.println();
output.println("Test finished.");
}
}
}

What happened ?

The library AT24CxEeprom is required to run the sketch. When connecting an AT24C512 and trying to read a complete eeprom page with a size of 128 Bytes, the processor reboots. It seems that the RingBuffer is corrupted. When only half of a page (64 bytes) are requested, everything works properly. Ist seems that the crash happens, when the requested quantity of bytes is greater than SERIAL_BUFFER

How to reproduce ?

Just take the provided sketch and add the recent version of library AT24CxEeprom.

Debug Log

No response

Screenshots

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions