adafruit / adafruit/Adafruit_nRF52_Arduino
TwoWire library crashes, when quantity parameter in request_from() function is greater than SERIAL_BUFFER_SIZE.
- Dominant language
- C
- Stars
- 699
- Forks
- 570
- PR merge metrics
- No merged PRs in 30d
Description
### 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
#include "AT24CxEeprom.h"
#if defined SIZE_MAX
static size_t sizeMax() {return SIZE_MAX;}
#else
#include
static size_t sizeMax() {return std::numeric_limits::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_
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with Wire.h and the nRF52840 TwoWire driver, focusing on request_from(), SERIAL_BUFFER_SIZE, and the RingBuffer behavior described in the reproduction sketch. Re-run the supplied AT24CxEeprom sketch with 128-byte and 64-byte reads; done means the larger request no longer reboots the processor or corrupts the ring buffer.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- arduino, c
- Domain
- embedded-iot
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100