Serial.print() feeds the data into the TX buffer one character at a time (through the Print class's inherited .write() function which HardwareSerial implements). If there isn't enough room in the TX buffer for the next character it waits for there to be room available.
Characters are removed one at a time from the TX buffer and sent through the physical UART by the UART's TX interrupt.
To put it in more detail:
- When you call
Serial.print()it's actually callingPrint.print(), becausePrintis a parent class of theHardwareSerialclass. Print.print()repeatedly callsPrint.write()for each character to print.Print.write()is a pure virtual function (which means it's only got the definition in thePrintclass and child classes must implement it).HardwareSerial.write()implements thePrint.write()function which takes the character and (with possible blocking while waiting for space) adds it to the TX buffer.Serialis an instance of theHardwareSerialclass.