@@ -38,8 +38,11 @@ TwoWire::TwoWire(uint8_t bus_num)
38
38
:num(bus_num & 1 )
39
39
,sda(-1 )
40
40
,scl(-1 )
41
+ ,bufferSize(I2C_BUFFER_LENGTH) // default Wire Buffer Size
42
+ ,rxBuffer(NULL )
41
43
,rxIndex(0 )
42
44
,rxLength(0 )
45
+ ,txBuffer(NULL )
43
46
,txLength(0 )
44
47
,txAddress(0 )
45
48
,_timeOutMillis(50 )
@@ -132,6 +135,87 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
132
135
return !i2cIsInit (num);
133
136
}
134
137
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
+
135
219
// Slave Begin
136
220
bool TwoWire::begin (uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
137
221
{
@@ -159,17 +243,22 @@ bool TwoWire::begin(uint8_t addr, int sdaPin, int sclPin, uint32_t frequency)
159
243
log_e (" Bus already started in Master Mode." );
160
244
goto end;
161
245
}
246
+ if (!allocateWireBuffer ()) {
247
+ // failed! Error Message already issued
248
+ goto end;
249
+ }
162
250
if (!initPins (sdaPin, sclPin)){
163
251
goto end;
164
252
}
165
253
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){
167
255
log_e (" Slave Init ERROR" );
168
256
goto end;
169
257
}
170
258
is_slave = true ;
171
259
started = true ;
172
260
end:
261
+ if (!started) freeWireBuffer ();
173
262
#if !CONFIG_DISABLE_HAL_LOCKS
174
263
// release lock
175
264
xSemaphoreGive (lock);
@@ -205,13 +294,18 @@ bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
205
294
started = true ;
206
295
goto end;
207
296
}
297
+ if (!allocateWireBuffer ()) {
298
+ // failed! Error Message already issued
299
+ goto end;
300
+ }
208
301
if (!initPins (sdaPin, sclPin)){
209
302
goto end;
210
303
}
211
304
err = i2cInit (num, sda, scl, frequency);
212
305
started = (err == ESP_OK);
213
306
214
307
end:
308
+ if (!started) freeWireBuffer ();
215
309
#if !CONFIG_DISABLE_HAL_LOCKS
216
310
// release lock
217
311
xSemaphoreGive (lock);
@@ -239,6 +333,7 @@ bool TwoWire::end()
239
333
} else if (i2cIsInit (num)){
240
334
err = i2cDeinit (num);
241
335
}
336
+ freeWireBuffer ();
242
337
#if !CONFIG_DISABLE_HAL_LOCKS
243
338
// release lock
244
339
xSemaphoreGive (lock);
@@ -325,12 +420,26 @@ void TwoWire::beginTransmission(uint16_t address)
325
420
txLength = 0 ;
326
421
}
327
422
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
+ */
328
433
uint8_t TwoWire::endTransmission (bool sendStop)
329
434
{
330
435
if (is_slave){
331
436
log_e (" Bus is in Slave Mode" );
332
437
return 4 ;
333
438
}
439
+ if (txBuffer == NULL ){
440
+ log_e (" NULL TX buffer pointer" );
441
+ return 4 ;
442
+ }
334
443
esp_err_t err = ESP_OK;
335
444
if (sendStop){
336
445
err = i2cWrite (num, txAddress, txBuffer, txLength, _timeOutMillis);
@@ -360,6 +469,10 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
360
469
log_e (" Bus is in Slave Mode" );
361
470
return 0 ;
362
471
}
472
+ if (rxBuffer == NULL || txBuffer == NULL ){
473
+ log_e (" NULL buffer pointer" );
474
+ return 0 ;
475
+ }
363
476
esp_err_t err = ESP_OK;
364
477
if (nonStop
365
478
#if !CONFIG_DISABLE_HAL_LOCKS
@@ -401,7 +514,11 @@ size_t TwoWire::requestFrom(uint16_t address, size_t size, bool sendStop)
401
514
402
515
size_t TwoWire::write (uint8_t data)
403
516
{
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) {
405
522
return 0 ;
406
523
}
407
524
txBuffer[txLength++] = data;
@@ -428,6 +545,10 @@ int TwoWire::available(void)
428
545
int TwoWire::read (void )
429
546
{
430
547
int value = -1 ;
548
+ if (rxBuffer == NULL ){
549
+ log_e (" NULL RX buffer pointer" );
550
+ return value;
551
+ }
431
552
if (rxIndex < rxLength) {
432
553
value = rxBuffer[rxIndex++];
433
554
}
@@ -437,6 +558,10 @@ int TwoWire::read(void)
437
558
int TwoWire::peek (void )
438
559
{
439
560
int value = -1 ;
561
+ if (rxBuffer == NULL ){
562
+ log_e (" NULL RX buffer pointer" );
563
+ return value;
564
+ }
440
565
if (rxIndex < rxLength) {
441
566
value = rxBuffer[rxIndex];
442
567
}
@@ -520,6 +645,10 @@ void TwoWire::onReceiveService(uint8_t num, uint8_t* inBytes, size_t numBytes, b
520
645
if (!wire->user_onReceive ){
521
646
return ;
522
647
}
648
+ if (wire->rxBuffer == NULL ){
649
+ log_e (" NULL RX buffer pointer" );
650
+ return ;
651
+ }
523
652
for (uint8_t i = 0 ; i < numBytes; ++i){
524
653
wire->rxBuffer [i] = inBytes[i];
525
654
}
@@ -534,6 +663,10 @@ void TwoWire::onRequestService(uint8_t num, void * arg)
534
663
if (!wire->user_onRequest ){
535
664
return ;
536
665
}
666
+ if (wire->txBuffer == NULL ){
667
+ log_e (" NULL TX buffer pointer" );
668
+ return ;
669
+ }
537
670
wire->txLength = 0 ;
538
671
wire->user_onRequest ();
539
672
if (wire->txLength ){
0 commit comments