Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9bceb28

Browse filesBrowse files
authored
Adds Wire::setBufferSize function (espressif#7016)
1 parent 178aee8 commit 9bceb28
Copy full SHA for 9bceb28

File tree

2 files changed

+148
-5
lines changed
Filter options

2 files changed

+148
-5
lines changed

‎libraries/Wire/src/Wire.cpp

Copy file name to clipboardExpand all lines: libraries/Wire/src/Wire.cpp
+135-2Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ TwoWire::TwoWire(uint8_t bus_num)
3838
:num(bus_num & 1)
3939
,sda(-1)
4040
,scl(-1)
41+
,bufferSize(I2C_BUFFER_LENGTH) // default Wire Buffer Size
42+
,rxBuffer(NULL)
4143
,rxIndex(0)
4244
,rxLength(0)
45+
,txBuffer(NULL)
4346
,txLength(0)
4447
,txAddress(0)
4548
,_timeOutMillis(50)
@@ -132,6 +135,87 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
132135
return !i2cIsInit(num);
133136
}
134137

138+
bool TwoWire::allocateWireBuffer(void)
139+
{
140+
// or both buffer can be allocated or none will be
141+
if (rxBuffer == NULL) {
142+
rxBuffer = (uint8_t *)malloc(bufferSize);
143+
if (rxBuffer == NULL) {
144+
log_e("Can't allocate memory for I2C_%d rxBuffer", num);
145+
return false;
146+
}
147+
}
148+
if (txBuffer == NULL) {
149+
txBuffer = (uint8_t *)malloc(bufferSize);
150+
if (txBuffer == NULL) {
151+
log_e("Can't allocate memory for I2C_%d txBuffer", num);
152+
freeWireBuffer(); // free rxBuffer for safety!
153+
return false;
154+
}
155+
}
156+
// in case both were allocated before, they must have the same size. All good.
157+
return true;
158+
}
159+
160+
void TwoWire::freeWireBuffer(void)
161+
{
162+
if (rxBuffer != NULL) {
163+
free(rxBuffer);
164+
rxBuffer = NULL;
165+
}
166+
if (txBuffer != NULL) {
167+
free(txBuffer);
168+
txBuffer = NULL;
169+
}
170+
}
171+
172+
size_t TwoWire::setBufferSize(size_t bSize)
173+
{
174+
// Maximum size .... HEAP limited ;-)
175+
if (bSize < 32) { // 32 bytes is the I2C FIFO Len for ESP32/S2/S3/C3
176+
log_e("Minimum Wire Buffer size is 32 bytes");
177+
return 0;
178+
}
179+
180+
#if !CONFIG_DISABLE_HAL_LOCKS
181+
if(lock == NULL){
182+
lock = xSemaphoreCreateMutex();
183+
if(lock == NULL){
184+
log_e("xSemaphoreCreateMutex failed");
185+
return 0;
186+
}
187+
}
188+
//acquire lock
189+
if(xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
190+
log_e("could not acquire lock");
191+
return 0;
192+
}
193+
#endif
194+
// allocateWireBuffer allocates memory for both pointers or just free them
195+
if (rxBuffer != NULL || txBuffer != NULL) {
196+
// if begin() has been already executed, memory size changes... data may be lost. We don't care! :^)
197+
if (bSize != bufferSize) {
198+
// we want a new buffer size ... just reset buffer pointers and allocate new ones
199+
freeWireBuffer();
200+
bufferSize = bSize;
201+
if (!allocateWireBuffer()) {
202+
// failed! Error message already issued
203+
bSize = 0; // returns error
204+
log_e("Buffer allocation failed");
205+
}
206+
} // else nothing changes, all set!
207+
} else {
208+
// no memory allocated yet, just change the size value - allocation in begin()
209+
bufferSize = bSize;
210+
}
211+
#if !CONFIG_DISABLE_HAL_LOCKS
212+
//release lock
213+
xSemaphoreGive(lock);
214+
215+
#endif
216+
return bSize;
217+
}
218+
135219
// Slave Begin
136220
bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
137221
{
@@ -159,17 +243,22 @@ bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
159243
log_e("Bus already started in Master Mode.");
160244
goto end;
161245
}
246+
if (!allocateWireBuffer()) {
247+
// failed! Error Message already issued
248+
goto end;
249+
}
162250
if(!initPins(sdaPin, sclPin)){
163251
goto end;
164252
}
165253
i2cSlaveAttachCallbacks(num, onRequestService, onReceiveService, this);
166-
if(i2cSlaveInit(num, sda, scl, addr, frequency, I2C_BUFFER_LENGTH, I2C_BUFFER_LENGTH) != ESP_OK){
254+
if(i2cSlaveInit(num, sda, scl, addr, frequency, bufferSize, bufferSize) != ESP_OK){
167255
log_e("Slave Init ERROR");
168256
goto end;
169257
}
170258
is_slave = true;
171259
started = true;
172260
end:
261+
if (!started) freeWireBuffer();
173262
#if !CONFIG_DISABLE_HAL_LOCKS
174263
//release lock
175264
xSemaphoreGive(lock);
@@ -205,13 +294,18 @@ bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
205294
started = true;
206295
goto end;
207296
}
297+
if (!allocateWireBuffer()) {
298+
// failed! Error Message already issued
299+
goto end;
300+
}
208301
if(!initPins(sdaPin, sclPin)){
209302
goto end;
210303
}
211304
err = i2cInit(num, sda, scl, frequency);
212305
started = (err == ESP_OK);
213306

214307
end:
308+
if (!started) freeWireBuffer();
215309
#if !CONFIG_DISABLE_HAL_LOCKS
216310
//release lock
217311
xSemaphoreGive(lock);
@@ -239,6 +333,7 @@ bool TwoWire::end()
239333
} else if(i2cIsInit(num)){
240334
err = i2cDeinit(num);
241335
}
336+
freeWireBuffer();
242337
#if !CONFIG_DISABLE_HAL_LOCKS
243338
//release lock
244339
xSemaphoreGive(lock);
@@ -325,12 +420,26 @@ void TwoWire::beginTransmission(uint16_t address)
325420
txLength = 0;
326421
}
327422

423+
/*
424+
https://www.arduino.cc/reference/en/language/functions/communication/wire/endtransmission/
425+
endTransmission() returns:
426+
0: success.
427+
1: data too long to fit in transmit buffer.
428+
2: received NACK on transmit of address.
429+
3: received NACK on transmit of data.
430+
4: other error.
431+
5: timeout
432+
*/
328433
uint8_t TwoWire::endTransmission(bool sendStop)
329434
{
330435
if(is_slave){
331436
log_e("Bus is in Slave Mode");
332437
return 4;
333438
}
439+
if (txBuffer == NULL){
440+
log_e("NULL TX buffer pointer");
441+
return 4;
442+
}
334443
esp_err_t err = ESP_OK;
335444
if(sendStop){
336445
err = i2cWrite(num, txAddress, txBuffer, txLength, _timeOutMillis);
@@ -360,6 +469,10 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
360469
log_e("Bus is in Slave Mode");
361470
return 0;
362471
}
472+
if (rxBuffer == NULL || txBuffer == NULL){
473+
log_e("NULL buffer pointer");
474+
return 0;
475+
}
363476
esp_err_t err = ESP_OK;
364477
if(nonStop
365478
#if !CONFIG_DISABLE_HAL_LOCKS
@@ -401,7 +514,11 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
401514

402515
size_t TwoWire::write(uint8_t data)
403516
{
404-
if(txLength >= I2C_BUFFER_LENGTH) {
517+
if (txBuffer == NULL){
518+
log_e("NULL TX buffer pointer");
519+
return 0;
520+
}
521+
if(txLength >= bufferSize) {
405522
return 0;
406523
}
407524
txBuffer[txLength++] = data;
@@ -428,6 +545,10 @@ int TwoWire::available(void)
428545
int TwoWire::read(void)
429546
{
430547
int value = -1;
548+
if (rxBuffer == NULL){
549+
log_e("NULL RX buffer pointer");
550+
return value;
551+
}
431552
if(rxIndex < rxLength) {
432553
value = rxBuffer[rxIndex++];
433554
}
@@ -437,6 +558,10 @@ int TwoWire::read(void)
437558
int TwoWire::peek(void)
438559
{
439560
int value = -1;
561+
if (rxBuffer == NULL){
562+
log_e("NULL RX buffer pointer");
563+
return value;
564+
}
440565
if(rxIndex < rxLength) {
441566
value = rxBuffer[rxIndex];
442567
}
@@ -520,6 +645,10 @@ void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, b
520645
if(!wire->user_onReceive){
521646
return;
522647
}
648+
if (wire->rxBuffer == NULL){
649+
log_e("NULL RX buffer pointer");
650+
return;
651+
}
523652
for(uint8_t i = 0; i < numBytes; ++i){
524653
wire->rxBuffer[i] = inBytes[i];
525654
}
@@ -534,6 +663,10 @@ void TwoWire::onRequestService(uint8_t num, void * arg)
534663
if(!wire->user_onRequest){
535664
return;
536665
}
666+
if (wire->txBuffer == NULL){
667+
log_e("NULL TX buffer pointer");
668+
return;
669+
}
537670
wire->txLength = 0;
538671
wire->user_onRequest();
539672
if(wire->txLength){

‎libraries/Wire/src/Wire.h

Copy file name to clipboardExpand all lines: libraries/Wire/src/Wire.h
+13-3Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@
3434
#endif
3535
#include "Stream.h"
3636

37+
// WIRE_HAS_BUFFER_SIZE means Wire has setBufferSize()
38+
#define WIRE_HAS_BUFFER_SIZE 1
39+
// WIRE_HAS_END means Wire has end()
40+
#define WIRE_HAS_END 1
41+
3742
#ifndef I2C_BUFFER_LENGTH
38-
#define I2C_BUFFER_LENGTH 128
43+
#define I2C_BUFFER_LENGTH 128 // Default size, if none is set using Wire::setBuffersize(size_t)
3944
#endif
4045
typedef void(*user_onRequest)(void);
4146
typedef void(*user_onReceive)(uint8_t*, int);
@@ -47,11 +52,12 @@ class TwoWire: public Stream
4752
int8_t sda;
4853
int8_t scl;
4954

50-
uint8_t rxBuffer[I2C_BUFFER_LENGTH];
55+
size_t bufferSize;
56+
uint8_t *rxBuffer;
5157
size_t rxIndex;
5258
size_t rxLength;
5359

54-
uint8_t txBuffer[I2C_BUFFER_LENGTH];
60+
uint8_t *txBuffer;
5561
size_t txLength;
5662
uint16_t txAddress;
5763

@@ -68,6 +74,8 @@ class TwoWire: public Stream
6874
static void onRequestService(uint8_t, void *);
6975
static void onReceiveService(uint8_t, uint8_t*, size_t, bool, void *);
7076
bool initPins(int sdaPin, int sclPin);
77+
bool allocateWireBuffer(void);
78+
void freeWireBuffer(void);
7179

7280
public:
7381
TwoWire(uint8_t bus_num);
@@ -93,6 +101,8 @@ class TwoWire: public Stream
93101
}
94102
bool end();
95103

104+
size_t setBufferSize(size_t bSize);
105+
96106
void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms
97107
uint16_t getTimeOut();
98108

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.