So here's a tl;dr of what I've found:
- SerialN.write(buf, len) on USARTSerial falls back to Print::write(const uint8_t*, size_t), which iterates byte-by-byte through write(uint8_t).
- On P2/Photon 2 that causes the UART TX path to be fed one byte at a time, introducing software-created inter-byte gaps and making write(buf, len) take much longer than expected.
- Adding a native USARTSerial::write(const uint8_t*, size_t) overload that routes to hal_usart_write_buffer() removes those gaps and restores expected buffered UART behavior.
When adding the following overload to spark_wiring_usartserial.cpp/.h (and exporting the symbol in the dynamlib) the issues go away.
spark_wiring_usartserial.h
virtual size_t write(const uint8_t* buffer, size_t size) override;
spark_wiring_usartserial.cpp
size_t USARTSerial::write(const uint8_t* buffer, size_t size)
{
if (!buffer || !size) {
return 0;
}
// attempt a write if blocking, or for non-blocking if there is room.
if (_blocking || hal_usart_available_data_for_write(_serial) > 0) {
ssize_t written = hal_usart_write_buffer(_serial, buffer, size, sizeof(*buffer));
return written > 0 ? written : 0;
}
return 0;
}
hal_dynamlib_usart.h
DYNALIB_FN(BASE_IDX2 + 7, hal_usart, hal_usart_write_buffer, ssize_t(hal_usart_interface_t serial, const void* buffer, size_t size, size_t elementSize))
//May also want to link hal_usart_read_buffer and hal_usart_peek_buffer here
For 8 byte writes and an unmodified v6.4.0, Serial2.write(buffer,size) took ~420 µs to run, and has the inter-byte delays. In the scope shots, D7 is high for the duration of the individual Serial.write() calls.
Using Serial2.write(buffer,size) with an unmodified v6.4.0
For 8 byte writes after patching spark_wiring_usartserial.cpp, Serial2.write(buffer,size) took ~50 µs to run and runs without inter-byte delays.
Using Serial2.write(buffer,size) after adding write(const uint8_t* buffer, size_t size) to spark_wiring_usartserial.cpp
I also looked at the other Serials for 8 and 64 byte writes using SerialN.write(buffer,size),
|
Serial1 |
Serial2 |
Serial3 |
| 8 byte write, v6.4.0 (µs) |
379 |
397 |
367 |
| 8 byte write, mod v6.4.0 (µs) |
71 |
27 |
64 |
| 64 byte write, v6.4.0 (µs) |
2826 |
3302 |
2840 |
| 64 byte write, mod v6.4.0 (µs) |
80 |
30 |
64 |
64 byte send on Serials 1, 2, and 3 for unmodified v6.4.0
64 byte send on Serials 1, 2, and 3 for modified v6.4.0
So with these changes, all 3 UART interfaces on the P2 are able to transmit without inter-byte delays and no longer waits for the entire send.
@rickkas7 let me know what you think. If this should be rolled into the develop branch I don't mind making a PR but I'm not sure what tests should be added or changed.