@@ -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
136220bool 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 ;
172260end:
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
214307end:
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+ */
328433uint8_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
402515size_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)
428545int 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)
437558int 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 ){
0 commit comments