Channel capacities

From TX and RX point of perspective

Baudrate (short BR) is normally picked from 300,600,1200,2400,4800,9600,19200,38400,57600 or 115200.

but can in principle be what you want (upper limit is often lower than 1 Mbit/sec)

Byte assumptions used in the following

  • 8 bit in a byte (serial ports often support 5,6,7,8 bit

  • 1 startbit

  • 1 stopbit

  • 2 bits idle time between two bytes transmitted

  • no parity bit

Some kitchen table math:

  • TX capacity is BR/(8+1+1+2) (8+1+1+2 from above)

  • Time to TX Buffer capacity (TXB) will be full within TXB/( BR/(8+1+1+2) ) second

  • Time to fill RX Buffer capacity with (RXB) will be full within RXB/( BR/(8+1+1+2)) second

Some selected baudrates
baudrate:                  600 1200 2400 4800   9600  19200 38400 57600  115200
bytes/sec                   50  100  200  400    800   1600  3200  4800    9600

time to TX 1 byte           20   10    5  2,5   1,25  0,625 0,313 0,208  0,104 [msec]

time to fill 16 byte buf   320   160  80   40     20     10     5   3,3   1,7  [msec]

time to fill 64 byte buf  1280   640 320  160     80     40    20  13,3   6,7  [msec]

note: most Arduinos has 64 byte RX buffer and 16 byte TX buffer

As an example the figures above shows that if your serial interface is running 19200 and you do have a 64 byte RX buffer, you have to read the port at least every 40 msec is the sender to you will use the max capacity AND you do not like to miss bytes.

So please consider a databudget for your serial ports as well as other communication interfaces.

TX buffering considerations

When TXing your writeSerial(just a name for serial write function) function will either deliver byte to be send directly in the UART transmitter or deliver it to thx TX buffer and the transmission will be done by an interrupt service routine which is triggered every time a single byte has been transmitted.

An asynchronous transmit.

So as long you dont fill the TX buffer your TX call writeSerial will take nearluy no time.

A) If the TX buffer is full you will either immediate return with a return code stating could not TX your byte

or ….

B) You will wait until a byte is transferred so a single slot will be available for you.

  • 9600 baud

  • 165 byte TX buffer

  • we want to TX 100 bytes just now

A) case situation
You have to - repeatly - call writeSerial until all is TX'ed

B) case situation
Well from here kitche table math.

  • It takes approx 0 sec to fill an empty TX buffer

  • It takes (100-16)*1,25 msec = 105 msec to send the rest

  • The 105 msec is often implemented by busy waiting eg while (!space-in-buf) {}

105 msec can be very long time.
If your program or task has cyclic behavior you period time must be larger than 105 msec.

In both cases …

No need to say more - I hope.

RX buffering considerations

Look in the table above. You can see how often you must service or empty

RX timeout

Often there is a built in timeout functionallity in your readSerial. It is common the the timeout is configurable.

The timeout let you return from the readSerial if the RX buffer is empty and nothing has been received within the timeout period.

To set timeout on Arduino serial port Serial use Serial.setTimeout(<timeout>) timeout is in milliseconds.

The timeout is implemented as busty waiting. So it takes your CPU time - beware.

Rules of thumb

TX

Avoid TX'ing a packet which is larger than the TX outgoing buffer. If you TX more than TX buffer you will be (busy) waiting until the last byte to TX is moved to TX buffer.
See calculations above

Do not forget at data budget. See max TX rates above in the table.

RX

Its always a good idea to have larger RX buffer than TX buffer. Mainly because it will minimize data loss if you have problems servicing RX buffer before it overflows.

In non kernel based systems - or kernel based system with serial drivers not using kernel passive waiting techniques - you will normally use busy waiting before you receive a byte or end up in a timeout == no bye received. So if you have a timeout of 1000 msec and no bytes i received you will do busy waiting for 1000 msec. NO problems if you do have anything to do but in a non kernel setup you will be delayed 1 sec and with a addon realtime kernel like krnl of freeRTOS you may consume CPU time others could have used.

So minimizing active waiting if possible. Maybe check is there is the 10 bytes you are waiting for is in the RX buffer and then read them.

There is no golden rule but think about it.

Multi tasking or realtime operating systems considerations.

A realtime operating system or kernel may provide proper crafted drivers which handle all waiting and timeout as passive waiting. It can be waiting by a semaphore or other realtime constructs. So not CPU time is wasted.

BUT …

If you are using krnl(by me) or arduino ports of FreeRTOS or other realtime extensions they might just use the drivers til serial, i2c etc provided as a part of the distributions.

And they do use busy waiting because the drivers are written for single program use.

So beware - and b ready to be surpriced in one way or another.

ESP32 and freeRTOS and waiting

The ESP32 is a duo kernel CPU. The whole driver system is build around freeRTOS so - as far as I can see - they do handle interrupts, waiting etc in the right way(passive) - by use of freeRTOS calls. So waste of CPU time is minimized.

BTW - Do you know Amazon own freeRTOS. They did buy it for IOT use.

OTHER CPUS

If you have some info regarding these items like (serial) drivers handle busy/passive waiting etc I woul dbe happy to hear about it :-)