Skip to content

Commit 420a590

Browse files
committed
finish support for chaining transactions and formatting cleanup
1 parent 3acc3c4 commit 420a590

6 files changed

Lines changed: 45 additions & 35 deletions

File tree

cores/arduino/SERCOM.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,8 @@ SercomTxn* SERCOM::stopTransmissionUART(SercomUartError error)
319319
return nullptr;
320320

321321
// Call completion callback before deciding to dequeue
322-
if (txn->onComplete)
323-
txn->onComplete(txn->user, static_cast<int>(error));
322+
if (txn->onComplete)
323+
txn->onComplete(txn->user, static_cast<int>(error));
324324

325325
// Check if callback wants to chain another phase
326326
if (txn->chainNext) {
@@ -466,8 +466,8 @@ SercomTxn* SERCOM::stopTransmissionSPI(SercomSpiError error)
466466
return nullptr;
467467

468468
// Call completion callback before deciding to dequeue
469-
if (txn->onComplete)
470-
txn->onComplete(txn->user, static_cast<int>(error));
469+
if (txn->onComplete)
470+
txn->onComplete(txn->user, static_cast<int>(error));
471471

472472
// Check if callback wants to chain another phase
473473
if (txn->chainNext) {

cores/arduino/Uart.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ class Uart : public HardwareSerial
5252

5353
operator bool() { return true; }
5454

55+
// Accessor for SERCOM peripheral (for direct async transaction enqueuing)
56+
SERCOM* getSercom(void) const { return sercom; }
57+
5558
private:
5659
SERCOM *sercom;
5760
RingBuffer rxBuffer;

libraries/SPI/SPI.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ void SPIClass::transfer(const void *txbuf, void *rxbuf, size_t count,
258258
txn->length = count;
259259
txn->onComplete = onComplete ? onComplete : &SPIClass::onTxnComplete;
260260
txn->user = onComplete ? user : this;
261+
txn->chainNext = false;
261262
txnDone = false;
262263
txnStatus = 0;
263264

libraries/SPI/SPI.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class SPIClass {
124124
void onService(void);
125125
void waitForTransfer(void);
126126
bool isBusy(void);
127+
SERCOM* getSercom(void) const { return _p_sercom; }
127128

128129
// Transaction Functions
129130
void usingInterrupt(int interruptNumber);

libraries/Wire/Wire.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit, uin
105105
// Allocate fresh transaction from pool and copy loader data
106106
SercomTxn* txn = allocateTxn();
107107
*txn = loader;
108+
txn->chainNext = false;
108109

109110
// For async callbacks, pass txn as user so callback can access txn->rxPtr/length directly
110111
// For sync calls, pass 'this' so onTxnComplete can update txnStatus/txnDone
@@ -181,11 +182,15 @@ uint8_t TwoWire::endTransmission(bool stopBit, void (*onComplete)(void* user, in
181182
// Allocate a fresh transaction from the pool and copy staged data from loader
182183
SercomTxn* txn = allocateTxn();
183184
*txn = loader; // Copy staged transaction data
185+
txn->chainNext = false;
184186

185187
// Set parameters that weren't known during beginTransmission/write
186188
txn->config = stopBit ? I2C_CFG_STOP : 0;
187189
txn->onComplete = onComplete ? onComplete : &TwoWire::onTxnComplete;
188-
txn->user = (user == nullptr) ? this : user;
190+
if (onComplete)
191+
txn->user = (user == nullptr) ? txn : user;
192+
else
193+
txn->user = this;
189194

190195
awaitingAddressAck = true;
191196
txnDone = false;

libraries/Wire/Wire.h

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -50,35 +50,35 @@ class TwoWire : public Stream
5050
// If onComplete is nullptr, this blocks for legacy sync behavior.
5151
// If onComplete is non-null, this enqueues and returns immediately (async).
5252
uint8_t endTransmission(bool stopBit = true,
53-
void (*onComplete)(void* user, int status) = nullptr,
54-
void* user = nullptr);
53+
void (*onComplete)(void *user, int status) = nullptr,
54+
void *user = nullptr);
5555

5656
// If onComplete is nullptr, this blocks for legacy sync behavior.
5757
// If onComplete is non-null, this enqueues and returns immediately (async).
5858
// If rxBuffer is nullptr, the internal buffer is used; otherwise rxBuffer is used.
5959
uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit = true,
60-
uint8_t* rxBuffer = nullptr,
61-
void (*onComplete)(void* user, int status) = nullptr,
62-
void* user = nullptr);
60+
uint8_t *rxBuffer = nullptr,
61+
void (*onComplete)(void *user, int status) = nullptr,
62+
void *user = nullptr);
6363

6464
size_t write(uint8_t data);
6565
// 3-arg write: when setExternal=true, data is used directly (zero-copy) and
6666
// quantity is treated as both length and capacity; subsequent write() calls return 0.
6767
// For streaming > WIRE_BUFFER_LENGTH or async usage, call setTxBuffer() before write()
6868
// on every transaction.
69-
size_t write(const uint8_t * data, size_t quantity, bool setExternal = false);
69+
size_t write(const uint8_t *data, size_t quantity, bool setExternal = false);
7070

7171
virtual int available(void);
7272
virtual int read(void);
7373
virtual int peek(void);
7474
virtual void flush(void);
75-
void onReceive(void(*)(int));
76-
void onRequest(void(*)(void));
77-
void setRxBuffer(uint8_t* buffer, size_t length);
78-
void setTxBuffer(uint8_t* buffer, size_t length);
75+
void onReceive(void (*)(int));
76+
void onRequest(void (*)(void));
77+
void setRxBuffer(uint8_t *buffer, size_t length);
78+
void setTxBuffer(uint8_t *buffer, size_t length);
7979
void clearRxBuffer(void);
8080
void resetRxBuffer(void);
81-
uint8_t* getRxBuffer(void);
81+
uint8_t *getRxBuffer(void);
8282
size_t getRxLength(void) const;
8383
inline SERCOM *getSercom(void) { return sercom; }
8484
inline const SERCOM *getSercom(void) const { return sercom; }
@@ -92,7 +92,7 @@ class TwoWire : public Stream
9292
inline void onService(void);
9393

9494
private:
95-
SERCOM * sercom;
95+
SERCOM *sercom;
9696
uint8_t _uc_pinSDA;
9797
uint8_t _uc_pinSCL;
9898

@@ -102,7 +102,7 @@ class TwoWire : public Stream
102102
static constexpr size_t WIRE_BUFFER_LENGTH = 255;
103103
uint8_t rxBuffer[WIRE_BUFFER_LENGTH];
104104
uint8_t txBuffer[WIRE_BUFFER_LENGTH];
105-
uint8_t* rxBufferPtr;
105+
uint8_t *rxBufferPtr;
106106
size_t rxBufferCapacity;
107107
size_t rxLength;
108108
size_t rxIndex;
@@ -114,22 +114,22 @@ class TwoWire : public Stream
114114
bool pendingReceive;
115115
int pendingReceiveLength;
116116
SercomTxn slaveTxn;
117-
SercomTxn loader; // Staging area for building transactions
117+
SercomTxn loader; // Staging area for building transactions
118118

119119
// Transaction pool for async operations (matches SERCOM queue depth)
120120
static constexpr size_t TXN_POOL_SIZE = 8;
121121
SercomTxn txnPool[TXN_POOL_SIZE];
122122
uint8_t txnPoolHead;
123123

124-
SercomTxn* allocateTxn();
125-
void freeTxn(SercomTxn* txn);
124+
SercomTxn *allocateTxn();
125+
void freeTxn(SercomTxn *txn);
126126

127127
// Callback user functions
128128
void (*onRequestCallback)(void);
129129
void (*onReceiveCallback)(int);
130130

131-
static void onTxnComplete(void* user, int status);
132-
static void onDeferredReceive(void* user, int length);
131+
static void onTxnComplete(void *user, int status);
132+
static void onDeferredReceive(void *user, int length);
133133

134134
// TWI clock frequency
135135
static const uint32_t TWI_CLOCK = 100000;
@@ -174,7 +174,7 @@ inline void TwoWire::onService(void)
174174
}
175175

176176
if (isMaster) {
177-
SercomTxn* txn = sercom->getCurrentTxnWIRE();
177+
SercomTxn *txn = sercom->getCurrentTxnWIRE();
178178
if (!txn) {
179179
sercom->clearINTFLAG();
180180
return;
@@ -222,7 +222,7 @@ inline void TwoWire::onService(void)
222222
}
223223
else {
224224
if (flags & SERCOM_I2CS_INTFLAG_ERROR) {
225-
SercomWireError err = SercomWireError::UNKNOWN_ERROR;;
225+
SercomWireError err = SercomWireError::UNKNOWN_ERROR;
226226

227227
if (status & SERCOM_I2CS_STATUS_BUSERR)
228228
err = SercomWireError::BUS_ERROR;
@@ -239,14 +239,14 @@ inline void TwoWire::onService(void)
239239
}
240240

241241
// To avoid unnecessary clock cycles for register reads, avoid using inline getters
242-
bool isMasterRead = (status & SERCOM_I2CS_STATUS_DIR); // Master Read / Slave Transmit
243-
bool sr = (status & SERCOM_I2CS_STATUS_SR); // Repeated Start detected
244-
bool prec = (flags & SERCOM_I2CS_INTFLAG_PREC); // Stop detected
245-
bool amatch = (flags & SERCOM_I2CS_INTFLAG_AMATCH); // Address Match detected
246-
bool drdy = (flags & SERCOM_I2CS_INTFLAG_DRDY); // Data Ready detected
242+
bool isMasterRead = (status & SERCOM_I2CS_STATUS_DIR); // Master Read / Slave Transmit
243+
bool sr = (status & SERCOM_I2CS_STATUS_SR); // Repeated Start detected
244+
bool prec = (flags & SERCOM_I2CS_INTFLAG_PREC); // Stop detected
245+
bool amatch = (flags & SERCOM_I2CS_INTFLAG_AMATCH); // Address Match detected
246+
bool drdy = (flags & SERCOM_I2CS_INTFLAG_DRDY); // Data Ready detected
247247

248248
// Stop or Restart detected - defer receive callback
249-
if(prec || (amatch && sr && !isMasterRead))
249+
if (prec || (amatch && sr && !isMasterRead))
250250
{
251251
pendingReceive = true;
252252
pendingReceiveLength = available();
@@ -256,14 +256,14 @@ inline void TwoWire::onService(void)
256256

257257
// Address Match - setup transaction
258258
// AACKEN enabled: address ACK is automatic, no manual ACK/clear needed
259-
else if(amatch)
259+
else if (amatch)
260260
{
261-
if(isMasterRead) // Master Read / Slave TX
261+
if (isMasterRead) // Master Read / Slave TX
262262
{
263263
// onRequestCallback runs in ISR context here. Deferring to PendSV
264264
// would require stalling DRDY or returning 0xFF until the buffer is filled.
265265
// onRequestCallback is what will set TwoWire::slaveTxn for the transaction.
266-
if(onRequestCallback)
266+
if (onRequestCallback)
267267
onRequestCallback();
268268

269269
// Ensure callback actually set slaveTxn.length; if not, stall with 0-length txn
@@ -298,7 +298,7 @@ inline void TwoWire::onService(void)
298298
}
299299

300300
// Data Ready - handle byte transfer
301-
if(drdy)
301+
if (drdy)
302302
{
303303
isMasterRead ? sercom->sendDataWIRE() : sercom->readDataWIRE();
304304

0 commit comments

Comments
 (0)