Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Wire::setBufferSize function #7016

Merged
merged 15 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 127 additions & 2 deletions libraries/Wire/src/Wire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ TwoWire::TwoWire(uint8_t bus_num)
:num(bus_num & 1)
,sda(-1)
,scl(-1)
,BufferSize(I2C_BUFFER_LENGTH) // default Wire Buffer Size
,rxBuffer(NULL)
,rxIndex(0)
,rxLength(0)
,txBuffer(NULL)
,txLength(0)
,txAddress(0)
,_timeOutMillis(50)
Expand Down Expand Up @@ -132,6 +135,81 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
return !i2cIsInit(num);
}

bool TwoWire::allocateWireBuffer(void)
{
// or both buffer can be allocated or none will be
if (rxBuffer == NULL) {
rxBuffer = (uint8_t *)malloc(BufferSize);
if (rxBuffer == NULL) {
log_e("Can't allocate memory for I2C_%d rxBuffer", num);
return false;
}
}
if (txBuffer == NULL) {
txBuffer = (uint8_t *)malloc(BufferSize);
if (txBuffer == NULL) {
log_e("Can't allocate memory for I2C_%d txBuffer", num);
freeWireBuffer(); // free rxBuffer for safety!
return false;
}
}
// in case both were allocated before, they must have the same size. All good.
return true;
}

void TwoWire::freeWireBuffer(void)
{
if (rxBuffer != NULL) {
free(rxBuffer);
rxBuffer = NULL;
}
if (txBuffer != NULL) {
free(txBuffer);
txBuffer = NULL;
}
}

size_t TwoWire::setBufferSize(size_t bSize)
{
// Maximum size .... HEAP limited ;-)
if (bSize < 32) { // 32 bytes is the I2C FIFO Len for ESP32/S2/S3/C3
log_e("Minimum Wire Buffer size is 32 bytes");
return 0;
}

#if !CONFIG_DISABLE_HAL_LOCKS
if(lock != NULL){
//acquire lock
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
log_e("could not acquire lock");
return 0;
}
#endif
P-R-O-C-H-Y marked this conversation as resolved.
Show resolved Hide resolved
// allocateWireBuffer allocates memory for both pointers or just free them
if (rxBuffer != NULL || txBuffer != NULL) {
// if begin() has been already executed, memory size changes... data may be lost. We don't care! :^)
if (bSize != BufferSize) {
// we want a new buffer size ... just reset buffer pointers and allocate new ones
freeWireBuffer();
BufferSize = bSize;
if (!allocateWireBuffer()) {
// failed! Error message already issued
bSize = 0; // returns error
}
} // else nothing changes, all set!
} else {
// no memory allocated yet, just change the size value - allocation in begin()
BufferSize = bSize;
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
}
#endif
return bSize;
P-R-O-C-H-Y marked this conversation as resolved.
Show resolved Hide resolved
}


// Slave Begin
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
{
Expand Down Expand Up @@ -159,11 +237,15 @@ bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
log_e("Bus already started in Master Mode.");
goto end;
}
if (!allocateWireBuffer()) {
// failed! Error Message already issued
goto end;
}
if(!initPins(sdaPin, sclPin)){
goto end;
}
i2cSlaveAttachCallbacks(num, onRequestService, onReceiveService, this);
if(i2cSlaveInit(num, sda, scl, addr, frequency, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH) != ESP_OK){
if(i2cSlaveInit(num, sda, scl, addr, frequency, BufferSize, BufferSize) != ESP_OK){
log_e("Slave Init ERROR");
goto end;
}
Expand Down Expand Up @@ -205,6 +287,10 @@ bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
started = true;
goto end;
}
if (!allocateWireBuffer()) {
// failed! Error Message already issued
goto end;
}
if(!initPins(sdaPin, sclPin)){
goto end;
}
P-R-O-C-H-Y marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -239,6 +325,7 @@ bool TwoWire::end()
} else if(i2cIsInit(num)){
err = i2cDeinit(num);
}
freeWireBuffer();
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive(lock);
Expand Down Expand Up @@ -325,12 +412,26 @@ void TwoWire::beginTransmission(uint16_t address)
txLength = 0;
}

/*
https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
endTransmission() returns:
0: success.
1: data too long to fit in transmit buffer.
2: received NACK on transmit of address.
3: received NACK on transmit of data.
4: other error.
5: timeout
*/
uint8_t TwoWire::endTransmission(bool sendStop)
{
if(is_slave){
log_e("Bus is in Slave Mode");
return 4;
}
if (txBuffer == NULL){
log_e("NULL TX buffer pointer");
return 4;
}
esp_err_t err = ESP_OK;
if(sendStop){
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
Expand Down Expand Up @@ -360,6 +461,10 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
log_e("Bus is in Slave Mode");
return 0;
}
if (rxBuffer == NULL || txBuffer == NULL){
log_e("NULL buffer pointer");
return 0;
}
esp_err_t err = ESP_OK;
if(nonStop
#if !CONFIG_DISABLE_HAL_LOCKS
Expand Down Expand Up @@ -401,7 +506,11 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)

size_t TwoWire::write(uint8_t data)
{
if(txLength >= I2C_BUFFER_LENGTH) {
if (txBuffer == NULL){
log_e("NULL TX buffer pointer");
return 0;
}
if(txLength >= BufferSize) {
return 0;
}
txBuffer[txLength++] = data;
Expand All @@ -428,6 +537,10 @@ int TwoWire::available(void)
int TwoWire::read(void)
{
int value = -1;
if (rxBuffer == NULL){
log_e("NULL RX buffer pointer");
return value;
}
if(rxIndex < rxLength) {
value = rxBuffer[rxIndex++];
}
Expand All @@ -437,6 +550,10 @@ int TwoWire::read(void)
int TwoWire::peek(void)
{
int value = -1;
if (rxBuffer == NULL){
log_e("NULL RX buffer pointer");
return value;
}
if(rxIndex < rxLength) {
value = rxBuffer[rxIndex];
}
Expand Down Expand Up @@ -520,6 +637,10 @@ void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, b
if(!wire->user_onReceive){
return;
}
if (wire->rxBuffer == NULL){
log_e("NULL RX buffer pointer");
return;
}
for(uint8_t i = 0; i < numBytes; ++i){
wire->rxBuffer[i] = inBytes[i];
}
Expand All @@ -534,6 +655,10 @@ void TwoWire::onRequestService(uint8_t num, void * arg)
if(!wire->user_onRequest){
return;
}
if (wire->txBuffer == NULL){
log_e("NULL TX buffer pointer");
return;
}
wire->txLength = 0;
wire->user_onRequest();
if(wire->txLength){
Expand Down
12 changes: 9 additions & 3 deletions libraries/Wire/src/Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@
#endif
#include "Stream.h"

#define WIRE_HAS_BUFFER_SIZE 1
P-R-O-C-H-Y marked this conversation as resolved.
Show resolved Hide resolved
#ifndef I2C_BUFFER_LENGTH
#define I2C_BUFFER_LENGTH 128
#define I2C_BUFFER_LENGTH 128 // Default size, if none is set using Wire::setBuffersize(size_t)
#endif
typedef void(*user_onRequest)(void);
typedef void(*user_onReceive)(uint8_t*, int);
Expand All @@ -47,11 +48,12 @@ class TwoWire: public Stream
int8_t sda;
int8_t scl;

uint8_t rxBuffer[I2C_BUFFER_LENGTH];
size_t BufferSize;
uint8_t *rxBuffer;
size_t rxIndex;
size_t rxLength;

uint8_t txBuffer[I2C_BUFFER_LENGTH];
uint8_t *txBuffer;
size_t txLength;
uint16_t txAddress;

Expand All @@ -68,6 +70,8 @@ class TwoWire: public Stream
static void onRequestService(uint8_t, void *);
static void onReceiveService(uint8_t, uint8_t*, size_t, bool, void *);
bool initPins(int sdaPin, int sclPin);
bool allocateWireBuffer(void);
void freeWireBuffer(void);

public:
TwoWire(uint8_t bus_num);
Expand All @@ -93,6 +97,8 @@ class TwoWire: public Stream
}
bool end();

size_t setBufferSize(size_t bSize);

void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms
uint16_t getTimeOut();

Expand Down