Skip to content

Commit 94ad97c

Browse files
committed
Enhance Wire buffers usage
- Do not call realloc each time, only if needed - Assume that user will use more than one time the same buffer size so avoid the call to realloc to decrease size - write: avoid copy byte/byte in the buffer Signed-off-by: Frederic.Pillon <[email protected]>
1 parent dfa41a2 commit 94ad97c

File tree

2 files changed

+64
-43
lines changed

2 files changed

+64
-43
lines changed

libraries/Wire/src/Wire.cpp

+54-40
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ extern "C" {
2929

3030
// Initialize Class Variables //////////////////////////////////////////////////
3131
uint8_t *TwoWire::rxBuffer = nullptr;
32+
uint8_t TwoWire::rxBufferAllocated = 0;
3233
uint8_t TwoWire::rxBufferIndex = 0;
3334
uint8_t TwoWire::rxBufferLength = 0;
3435

3536
uint8_t TwoWire::txAddress = 0;
3637
uint8_t *TwoWire::txBuffer = nullptr;
38+
uint8_t TwoWire::txBufferAllocated = 0;
3739
uint8_t TwoWire::txBufferIndex = 0;
3840
uint8_t TwoWire::txBufferLength = 0;
3941

@@ -66,11 +68,11 @@ void TwoWire::begin(uint8_t address)
6668
{
6769
rxBufferIndex = 0;
6870
rxBufferLength = 0;
69-
rxBuffer = resetBuffer(rxBuffer);
71+
resetRxBuffer();
7072

7173
txBufferIndex = 0;
7274
txBufferLength = 0;
73-
txBuffer = resetBuffer(txBuffer);
75+
resetTxBuffer();
7476

7577
transmitting = 0;
7678

@@ -101,8 +103,10 @@ void TwoWire::end(void)
101103
{
102104
free(txBuffer);
103105
txBuffer = nullptr;
106+
txBufferAllocated = 0;
104107
free(rxBuffer);
105108
rxBuffer = nullptr;
109+
rxBufferAllocated = 0;
106110
i2c_deinit(&_i2c);
107111
}
108112

@@ -115,7 +119,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
115119
{
116120
UNUSED(sendStop);
117121
if (master == true) {
118-
rxBuffer = allocateBuffer(rxBuffer, quantity);
122+
allocateRxBuffer(quantity);
119123
// error if no memory block available to allocate the buffer
120124
if(rxBuffer == nullptr){
121125
setWriteError();
@@ -224,10 +228,8 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
224228
break;
225229
}
226230

227-
//Reduce buffer size to free memory in case of large memory use
228-
if(txBufferLength > BUFFER_LENGTH) {
229-
txBuffer = resetBuffer(txBuffer);
230-
}
231+
// reset Tx buffer
232+
resetTxBuffer();
231233

232234
// reset tx buffer iterator vars
233235
txBufferIndex = 0;
@@ -255,7 +257,7 @@ size_t TwoWire::write(uint8_t data)
255257
{
256258
if(transmitting){
257259
// in master transmitter mode
258-
txBuffer = allocateBuffer(txBuffer, txBufferLength + 1);
260+
allocateTxBuffer(txBufferLength + 1);
259261
// error if no memory block available to allocate the buffer
260262
if(txBuffer == nullptr){
261263
setWriteError();
@@ -285,14 +287,20 @@ size_t TwoWire::write(uint8_t data)
285287
*/
286288
size_t TwoWire::write(const uint8_t *data, size_t quantity)
287289
{
288-
size_t nb = 0;
289-
290290
if(transmitting){
291291
// in master transmitter mode
292-
for(size_t i = 0; i < quantity; ++i){
293-
nb += write(data[i]);
292+
allocateTxBuffer(txBufferLength + quantity);
293+
// error if no memory block available to allocate the buffer
294+
if(txBuffer == nullptr){
295+
setWriteError();
296+
return 0;
294297
}
295-
return nb;
298+
// put bytes in tx buffer
299+
memcpy(&(txBuffer[txBufferIndex]), data, quantity);
300+
txBufferIndex= txBufferIndex + quantity;
301+
// update amount in buffer
302+
txBufferLength = txBufferIndex;
303+
return quantity;
296304
}else{
297305
// in slave send mode
298306
// reply to master
@@ -323,11 +331,12 @@ int TwoWire::read(void)
323331
value = rxBuffer[rxBufferIndex];
324332
++rxBufferIndex;
325333

326-
/* Reduce buffer size to free memory in case of large memory use when no more
327-
data available */
328-
if((rxBufferIndex == rxBufferLength) && (rxBufferLength > BUFFER_LENGTH)) {
329-
rxBuffer = resetBuffer(rxBuffer);
330-
}
334+
/* Commented as not I think it is not useful
335+
* but kept to show that it is possible to
336+
* reset rx buffer when no more data available */
337+
/*if(rxBufferIndex == rxBufferLength) {
338+
resetRxBuffer();
339+
}*/
331340
}
332341

333342
return value;
@@ -351,10 +360,10 @@ void TwoWire::flush(void)
351360
{
352361
rxBufferIndex = 0;
353362
rxBufferLength = 0;
354-
rxBuffer = resetBuffer(rxBuffer);
363+
resetRxBuffer();
355364
txBufferIndex = 0;
356365
txBufferLength = 0;
357-
txBuffer = resetBuffer(txBuffer);
366+
resetTxBuffer();
358367
}
359368

360369
// behind the scenes function that is called when data is received
@@ -373,9 +382,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
373382
}
374383
// copy twi rx buffer into local read buffer
375384
// this enables new reads to happen in parallel
376-
for(uint8_t i = 0; i < numBytes; ++i){
377-
rxBuffer[i] = inBytes[i];
378-
}
385+
memcpy(rxBuffer, inBytes, numBytes);
379386
// set rx iterator vars
380387
rxBufferIndex = 0;
381388
rxBufferLength = numBytes;
@@ -412,34 +419,41 @@ void TwoWire::onRequest( void (*function)(void) )
412419
}
413420

414421
/**
415-
* @brief Change the size of the buffer.
416-
* @param buffer: pointer to the allocated buffer
422+
* @brief Allocate the Rx/Tx buffer to the requested length if needed
423+
* @note Minimum allocated size is BUFFER_LENGTH)
417424
* @param length: number of bytes to allocate
418-
* @retval pointer to the new buffer location
419425
*/
420-
uint8_t *TwoWire::allocateBuffer(uint8_t *buffer, size_t length)
426+
inline void TwoWire::allocateRxBuffer(size_t length)
421427
{
428+
if(rxBufferAllocated < length) {
422429
// By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
423-
if(length < BUFFER_LENGTH) {
424-
length = BUFFER_LENGTH;
430+
if(length < BUFFER_LENGTH) { length = BUFFER_LENGTH; }
431+
rxBuffer = (uint8_t *)realloc(rxBuffer, length * sizeof(uint8_t));
432+
rxBufferAllocated = (rxBuffer != nullptr) ? length: 0;
425433
}
434+
}
426435

427-
buffer = (uint8_t *)realloc(buffer, length * sizeof(uint8_t));
428-
return buffer;
436+
inline void TwoWire::allocateTxBuffer(size_t length)
437+
{
438+
if(txBufferAllocated < length) {
439+
// By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
440+
if(length < BUFFER_LENGTH) { length = BUFFER_LENGTH; }
441+
txBuffer = (uint8_t *)realloc(txBuffer, length * sizeof(uint8_t));
442+
txBufferAllocated = (txBuffer != nullptr) ? length: 0;
443+
}
429444
}
430445

431446
/**
432-
* @brief Reset the buffer. Reduce its size to BUFFER_LENGTH.
433-
* @param buffer: pointer to the allocated buffer
434-
* @retval pointer to the new buffer location
447+
* @brief Reset Rx/Tx buffer content to 0
435448
*/
436-
uint8_t *TwoWire::resetBuffer(uint8_t *buffer)
449+
inline void TwoWire::resetRxBuffer(void)
437450
{
438-
buffer = (uint8_t *)realloc(buffer, BUFFER_LENGTH * sizeof(uint8_t));
439-
if(buffer != nullptr) {
440-
memset(buffer, 0, BUFFER_LENGTH);
441-
}
442-
return buffer;
451+
if (rxBuffer != nullptr) memset(rxBuffer, 0, rxBufferAllocated);
452+
}
453+
454+
inline void TwoWire::resetTxBuffer(void)
455+
{
456+
if (txBuffer != nullptr) memset(txBuffer, 0, txBufferAllocated);
443457
}
444458

445459
// Preinstantiate Objects //////////////////////////////////////////////////////

libraries/Wire/src/Wire.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ class TwoWire : public Stream
3737
{
3838
private:
3939
static uint8_t *rxBuffer;
40+
static uint8_t rxBufferAllocated;
4041
static uint8_t rxBufferIndex;
4142
static uint8_t rxBufferLength;
4243

4344
static uint8_t txAddress;
4445
static uint8_t *txBuffer;
46+
static uint8_t txBufferAllocated;
4547
static uint8_t txBufferIndex;
4648
static uint8_t txBufferLength;
4749

@@ -56,8 +58,11 @@ class TwoWire : public Stream
5658
static void onRequestService(void);
5759
static void onReceiveService(uint8_t*, int);
5860

59-
uint8_t *allocateBuffer(uint8_t *buffer, size_t length);
60-
uint8_t *resetBuffer(uint8_t *buffer);
61+
void allocateRxBuffer(size_t length);
62+
void allocateTxBuffer(size_t length);
63+
64+
void resetRxBuffer(void);
65+
void resetTxBuffer(void);
6166

6267
public:
6368
TwoWire();
@@ -73,7 +78,7 @@ class TwoWire : public Stream
7378
uint8_t endTransmission(uint8_t);
7479
uint8_t requestFrom(uint8_t, uint8_t);
7580
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
76-
uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t);
81+
uint8_t requestFrom(uint8_t, uint8_t, uint32_t, uint8_t, uint8_t);
7782
uint8_t requestFrom(int, int);
7883
uint8_t requestFrom(int, int, int);
7984
virtual size_t write(uint8_t);
@@ -92,6 +97,8 @@ class TwoWire : public Stream
9297
using Print::write;
9398
};
9499

100+
101+
95102
extern TwoWire Wire;
96103

97104
#endif

0 commit comments

Comments
 (0)