If you call the version of write with a pointer and size, then that entire string gets passed to the HAL layer as a pointer. The HAL layer does implement the FIFO. It has checks for the current FIFO depth and if there is more room in the FIFO then it will put the data there.
But then once it's got all the data loaded into the FIFO, it switches off the TXI interrupt. This would be fine except that our Arduino core uses that interrupt to set tx_done
and stop blocking. So it still doesn't happen until the transmission is complete.
The only version in UART
that writes directly to TDR
is write_raw
. The others call 'write' from the HAL layer.
1 Like
KurtE
May 21, 2024, 5:40pm
22
Thanks,
I was talking more in generality like with the Serial.print... And yep skipped that the actual work is done in the HAL layer...
You are right, it appears like the write(buf, len) is handled differently...
As I can see in simple sketch:
#include <UNOR4_digitalWriteFast.h>
// define
#define BAUDRATE 9600
#define UART2_TX_PIN (18u) // Pin A4
#define UART2_RX_PIN (19u) // Pin A5
#define DEBUG_PIN 2
// Instantiate the Serial2 class
UART _UART2_(UART2_TX_PIN, UART2_RX_PIN); // Makes Serial2 available on pin A4 Tx, A5 Tx
// Setup
void setup(void) {
Serial.begin(BAUDRATE);
while (!Serial && millis() < 8000) {}
Serial.println("Serial test");
pinMode(DEBUG_PIN, OUTPUT);
digitalWriteFast(DEBUG_PIN, LOW);
Serial2.begin(BAUDRATE);
}
const uint8_t num_buf[] = "0123456789";
// Main Loop
uint32_t loop_count = 0;
void loop(void) {
digitalToggleFast(DEBUG_PIN);
Serial2.print(++loop_count);
digitalToggleFast(DEBUG_PIN);
Serial2.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
digitalToggleFast(DEBUG_PIN);
Serial2.write(num_buf, sizeof(num_buf)-1);
Serial2.println();
digitalToggleFast(DEBUG_PIN);
delay(50);
}
You can see most of the prints return when the last two characters have been queued.
But the Write, shows it returns only after the last of the number buffer is output. But
again the println() again returns after the two bytes are queued.
Not sure if they fixed the storing two characters into TDR without checking if
the TDR is empty:
I don't see any check in the actual underlying code:
fsp/ra/fsp/src/r_sci_uart/r_sci_uart.c at master ยท renesas/fsp (github.com)
Should also try it on on Serial1 which I know does not have FIFO...
Yes, take the flush() out and I get the same result, it isnt doing anything. I am testing on the Minima
I tried running your script, but I still see Write() returning when the last two bytes are queued. I took out the last print and get this
// Main Loop
uint32_t loop_count = 0;
void loop(void) {
digitalWrite(DEBUG_PIN, HIGH);
Serial2.print(++loop_count);
digitalWrite(DEBUG_PIN, LOW);
Serial2.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
digitalWrite(DEBUG_PIN, HIGH);
Serial2.write(num_buf, sizeof(num_buf)-1);
// Serial2.println();
digitalWrite(DEBUG_PIN, LOW);
delay(50);
}
To me it looks like Print and Write behave the same way
print calls write. It just formats some types before it does.
I think I have found a solution to flush() not working. Please have a look at my Pull Request: GitHub - Hsubtnarg/ArduinoCore-renesas-serialflush: Fix Serial Flush so it only returns when transmission has completed . It works on Serial1 and Serial2
Testing with this code
// Main Loop
uint32_t loop_count = 0;
void loop(void) {
digitalWrite(DEBUG_PIN, HIGH);
Serial2.print(++loop_count);
Serial2.flush();
digitalWrite(DEBUG_PIN, LOW);
Serial2.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
Serial2.flush();
digitalWrite(DEBUG_PIN, HIGH);
Serial2.write(num_buf, sizeof(num_buf)-1);
Serial2.println();
Serial2.flush();
digitalWrite(DEBUG_PIN, LOW);
delay(50);
}
I now get his
It would be good if you could test it on your code