Skip to content

Commit dfa41a2

Browse files
fprfpistm
fpr
authored andcommitted
Change Wire Rx/Tx buffers managements
Buffers are now dynamically allocated (min size: BUFFER_LENGTH) Signed-off-by: fpr <[email protected]>
1 parent 4dc65c3 commit dfa41a2

File tree

5 files changed

+106
-32
lines changed

5 files changed

+106
-32
lines changed

cores/arduino/stm32/twi.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ void i2c_setTiming(i2c_t *obj, uint32_t frequency)
348348
* @retval read status
349349
*/
350350
i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
351-
uint8_t *data, uint8_t size)
351+
uint8_t *data, uint16_t size)
352352

353353
{
354354
i2c_status_e ret = I2C_ERROR;
@@ -375,17 +375,24 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
375375
* @param obj : pointer to i2c_t structure
376376
* @param data: pointer to data to be write
377377
* @param size: number of bytes to be write.
378-
* @retval none
378+
* @retval status
379379
*/
380-
void i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint8_t size)
380+
i2c_status_e i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint16_t size)
381381
{
382382
uint8_t i = 0;
383383

384+
// Protection to not override the TxBuffer
385+
if(size > I2C_TXRX_BUFFER_SIZE) {
386+
return I2C_ERROR;
387+
}
388+
384389
// Check the communication status
385390
for(i = 0; i < size; i++) {
386391
obj->i2cTxRxBuffer[i] = *(data+i);
387392
obj->i2cTxRxBufferSize++;
388393
}
394+
395+
return I2C_OK;
389396
}
390397

391398
/**
@@ -396,7 +403,7 @@ void i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint8_t size)
396403
* @param size: number of bytes to be read.
397404
* @retval read status
398405
*/
399-
i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint8_t size)
406+
i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint16_t size)
400407
{
401408
i2c_status_e ret = I2C_ERROR;
402409
uint32_t tickstart = HAL_GetTick();

cores/arduino/stm32/twi.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode,
148148
uint32_t ownAddress, uint8_t master);
149149
void i2c_deinit(i2c_t *obj);
150150
void i2c_setTiming(i2c_t *obj, uint32_t frequency);
151-
i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint8_t size);
152-
void i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint8_t size);
153-
i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint8_t size);
151+
i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint16_t size);
152+
i2c_status_e i2c_slave_write_IT(i2c_t *obj, uint8_t *data, uint16_t size);
153+
i2c_status_e i2c_master_read(i2c_t *obj, uint8_t dev_address, uint8_t *data, uint16_t size);
154154

155155
i2c_status_e i2c_IsDeviceReady(i2c_t *obj, uint8_t devAddr,uint32_t trials);
156156

libraries/Wire/keywords.txt

+6-7
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
# Methods and Functions (KEYWORD2)
1111
#######################################
1212

13-
begin KEYWORD2
14-
setClock KEYWORD2
13+
begin KEYWORD2
14+
setClock KEYWORD2
1515
beginTransmission KEYWORD2
16-
endTransmission KEYWORD2
17-
requestFrom KEYWORD2
18-
onReceive KEYWORD2
19-
onRequest KEYWORD2
16+
endTransmission KEYWORD2
17+
requestFrom KEYWORD2
18+
onReceive KEYWORD2
19+
onRequest KEYWORD2
2020

2121
#######################################
2222
# Instances (KEYWORD2)
@@ -28,4 +28,3 @@ Wire1 KEYWORD2
2828
#######################################
2929
# Constants (LITERAL1)
3030
#######################################
31-

libraries/Wire/src/Wire.cpp

+81-16
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ extern "C" {
2828
#include "Wire.h"
2929

3030
// Initialize Class Variables //////////////////////////////////////////////////
31-
uint8_t TwoWire::rxBuffer[BUFFER_LENGTH];
31+
uint8_t *TwoWire::rxBuffer = nullptr;
3232
uint8_t TwoWire::rxBufferIndex = 0;
3333
uint8_t TwoWire::rxBufferLength = 0;
3434

3535
uint8_t TwoWire::txAddress = 0;
36-
uint8_t TwoWire::txBuffer[BUFFER_LENGTH];
36+
uint8_t *TwoWire::txBuffer = nullptr;
3737
uint8_t TwoWire::txBufferIndex = 0;
3838
uint8_t TwoWire::txBufferLength = 0;
3939

@@ -66,9 +66,11 @@ void TwoWire::begin(uint8_t address)
6666
{
6767
rxBufferIndex = 0;
6868
rxBufferLength = 0;
69+
rxBuffer = resetBuffer(rxBuffer);
6970

7071
txBufferIndex = 0;
7172
txBufferLength = 0;
73+
txBuffer = resetBuffer(txBuffer);
7274

7375
transmitting = 0;
7476

@@ -97,6 +99,10 @@ void TwoWire::begin(int address)
9799

98100
void TwoWire::end(void)
99101
{
102+
free(txBuffer);
103+
txBuffer = nullptr;
104+
free(rxBuffer);
105+
rxBuffer = nullptr;
100106
i2c_deinit(&_i2c);
101107
}
102108

@@ -109,6 +115,13 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
109115
{
110116
UNUSED(sendStop);
111117
if (master == true) {
118+
rxBuffer = allocateBuffer(rxBuffer, quantity);
119+
// error if no memory block available to allocate the buffer
120+
if(rxBuffer == nullptr){
121+
setWriteError();
122+
return 0;
123+
}
124+
112125
if (isize > 0) {
113126
// send internal address; this mode allows sending a repeated start to access
114127
// some devices' internal registers. This function is executed by the hardware
@@ -128,12 +141,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
128141
endTransmission(false);
129142
}
130143

131-
// clamp to buffer length
132-
if(quantity > BUFFER_LENGTH){
133-
quantity = BUFFER_LENGTH;
134-
}
135144
// perform blocking read into buffer
136-
//uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
137145
uint8_t read = 0;
138146
if(I2C_OK == i2c_master_read(&_i2c, address << 1, rxBuffer, quantity))
139147
read = quantity;
@@ -216,9 +224,15 @@ uint8_t TwoWire::endTransmission(uint8_t sendStop)
216224
break;
217225
}
218226

227+
//Reduce buffer size to free memory in case of large memory use
228+
if(txBufferLength > BUFFER_LENGTH) {
229+
txBuffer = resetBuffer(txBuffer);
230+
}
231+
219232
// reset tx buffer iterator vars
220233
txBufferIndex = 0;
221234
txBufferLength = 0;
235+
222236
// indicate that we are done transmitting
223237
transmitting = 0;
224238
}
@@ -241,8 +255,9 @@ size_t TwoWire::write(uint8_t data)
241255
{
242256
if(transmitting){
243257
// in master transmitter mode
244-
// don't bother if buffer is full
245-
if(txBufferLength >= BUFFER_LENGTH){
258+
txBuffer = allocateBuffer(txBuffer, txBufferLength + 1);
259+
// error if no memory block available to allocate the buffer
260+
if(txBuffer == nullptr){
246261
setWriteError();
247262
return 0;
248263
}
@@ -254,27 +269,38 @@ size_t TwoWire::write(uint8_t data)
254269
}else{
255270
// in slave send mode
256271
// reply to master
257-
i2c_slave_write_IT(&_i2c,&data,1);
272+
if(i2c_slave_write_IT(&_i2c,&data,1) != I2C_OK) {
273+
return 0;
274+
}
258275
}
259276
return 1;
260277
}
261278

262-
// must be called in:
263-
// slave tx event callback
264-
// or after beginTransmission(address)
279+
/**
280+
* @brief This function must be called in slave Tx event callback or after
281+
* beginTransmission() and before endTransmission().
282+
* @param pdata: pointer to the buffer data
283+
* @param quantity: number of bytes to write
284+
* @retval number of bytes ready to write.
285+
*/
265286
size_t TwoWire::write(const uint8_t *data, size_t quantity)
266287
{
288+
size_t nb = 0;
289+
267290
if(transmitting){
268291
// in master transmitter mode
269292
for(size_t i = 0; i < quantity; ++i){
270-
write(data[i]);
293+
nb += write(data[i]);
271294
}
295+
return nb;
272296
}else{
273297
// in slave send mode
274298
// reply to master
275-
i2c_slave_write_IT(&_i2c,(uint8_t *)data,quantity);
299+
if(i2c_slave_write_IT(&_i2c, (uint8_t *)data, quantity) == I2C_OK) {
300+
return quantity;
301+
}
276302
}
277-
return quantity;
303+
return 0;
278304
}
279305

280306
// must be called in:
@@ -296,6 +322,12 @@ int TwoWire::read(void)
296322
if(rxBufferIndex < rxBufferLength){
297323
value = rxBuffer[rxBufferIndex];
298324
++rxBufferIndex;
325+
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+
}
299331
}
300332

301333
return value;
@@ -319,8 +351,10 @@ void TwoWire::flush(void)
319351
{
320352
rxBufferIndex = 0;
321353
rxBufferLength = 0;
354+
rxBuffer = resetBuffer(rxBuffer);
322355
txBufferIndex = 0;
323356
txBufferLength = 0;
357+
txBuffer = resetBuffer(txBuffer);
324358
}
325359

326360
// behind the scenes function that is called when data is received
@@ -377,6 +411,37 @@ void TwoWire::onRequest( void (*function)(void) )
377411
user_onRequest = function;
378412
}
379413

414+
/**
415+
* @brief Change the size of the buffer.
416+
* @param buffer: pointer to the allocated buffer
417+
* @param length: number of bytes to allocate
418+
* @retval pointer to the new buffer location
419+
*/
420+
uint8_t *TwoWire::allocateBuffer(uint8_t *buffer, size_t length)
421+
{
422+
// By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
423+
if(length < BUFFER_LENGTH) {
424+
length = BUFFER_LENGTH;
425+
}
426+
427+
buffer = (uint8_t *)realloc(buffer, length * sizeof(uint8_t));
428+
return buffer;
429+
}
430+
431+
/**
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
435+
*/
436+
uint8_t *TwoWire::resetBuffer(uint8_t *buffer)
437+
{
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;
443+
}
444+
380445
// Preinstantiate Objects //////////////////////////////////////////////////////
381446

382447
TwoWire Wire = TwoWire(); //D14-D15

libraries/Wire/src/Wire.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636
class TwoWire : public Stream
3737
{
3838
private:
39-
static uint8_t rxBuffer[BUFFER_LENGTH];
39+
static uint8_t *rxBuffer;
4040
static uint8_t rxBufferIndex;
4141
static uint8_t rxBufferLength;
4242

4343
static uint8_t txAddress;
44-
static uint8_t txBuffer[BUFFER_LENGTH];
44+
static uint8_t *txBuffer;
4545
static uint8_t txBufferIndex;
4646
static uint8_t txBufferLength;
4747

@@ -56,6 +56,9 @@ class TwoWire : public Stream
5656
static void onRequestService(void);
5757
static void onReceiveService(uint8_t*, int);
5858

59+
uint8_t *allocateBuffer(uint8_t *buffer, size_t length);
60+
uint8_t *resetBuffer(uint8_t *buffer);
61+
5962
public:
6063
TwoWire();
6164
TwoWire(uint8_t sda, uint8_t scl);

0 commit comments

Comments
 (0)