HW SW UART

Hardware based UARTS (universal asynchronous receiver transmitter) is really preferred. You just write a byte to a TX register and the UART then take care of the transmission, bit after bit.

TX seance simplified

An example: the uart is configure to 1200 baud. At byte capicity TX time of a byte is 10 milli seconds. Writing the byte to (an empty) TX register takes next to noting.

  1. sender call write function in driver

  2. if UART TX register is empty sender write TX byte to TX register in UART

  3. otherwise sender write the TX byte to the TX-buffer

  4. UART issue an interrupt when the byte is transmitted

  5. if there is bytes in the TX-buffer the interrupt routine write this to UART TX register

The same goes for receiving. It normally goes like:

RX seance simplified

  1. UART do an interrupt to signal a byte arrived

  2. ISR routing read byte from RX register and store it in a buffer or message queue

  3. Reader calls read function which either read e byte from the buffer

  4. or …

  5. wait until a byte has arrived or timeout limit in read call has been reached

Software based UART - aka bit banging

Is no HW uart is present in system or an additional UART is needed sometimes a software based UART is used.

FOr Arduino see her SoftwareSerial.h and SoftwareSerial.cpp.

SW UARTS may have bad impact on your timing

Two examples for TX and RX 1 byte at 4800 baud

SW UART TX of 1 byte @4800 baud

TX 1 byte @ 4800 baud takes 2.5 msec.

A std digital out goin pin is used.

It is all done by bit banging

  1. Interrupt is disabled

  2. startbit edge to low

  3. busy waiting 1 bit time -0.21 milli second

  4. bit 0 starting edge high or low

  5. busy waiting 1 bit time -0.21 milli second

  6. bit 1 starting edge high or low

  7. busy waiting 1 bit time -0.21 milli second

  8. bit 2 starting edge high or low

  9. busy waiting 1 bit time -0.21 milli second

  10. bit 3 starting edge high or low

  11. busy waiting 1 bit time -0.21 milli second

  12. bit 4 starting edge high or low

  13. busy waiting 1 bit time -0.21 milli second

  14. bit 5 starting edge high or low

  15. busy waiting 1 bit time -0.21 milli second

  16. bit 6 starting edge high or low

  17. busy waiting 1 bit time -0.21 milli second

  18. bit 7 starting edge high or low

  19. busy waiting 1 bit time -0.21 milli second

  20. stopbit starting edge high

  21. busy waiting 1 bit time -0.21 milli second

  22. Interrupt is now re-enabled

So the machine is running with interrupt disabled for 2.1 milli second.

SW UART RX of 1 byte @4800 baud

RX 1 byte @ 4800 baud takes 2.5 msec.

A std digital out goin pin is used.

It is all done by bit banging

  1. Interrupt register falling edge == startbit

  2. busy waiting 0.5 bit time -0.10 milli second

  3. read startbit - in middle of bit (bq of the 0.5 bittime delay above)

  4. busy waiting 1 bit time -0.21 milli second

  5. read bit 0 starting edge high or low

  6. busy waiting 1 bit time -0.21 milli second

  7. read bit 1 starting edge high or low

  8. busy waiting 1 bit time -0.21 milli second

  9. read bit 2 starting edge high or low

  10. busy waiting 1 bit time -0.21 milli second

  11. read read bit 3 starting edge high or low

  12. busy waiting 1 bit time -0.21 milli second

  13. read bit 4 starting edge high or low

  14. busy waiting 1 bit time -0.21 milli second

  15. read bit 5 starting edge high or low

  16. busy waiting 1 bit time -0.21 milli second

  17. read bit 6 starting edge high or low

  18. busy waiting 1 bit time -0.21 milli second

  19. read bit 7 starting edge high or low

  20. busy waiting 1 bit time -0.21 milli second

  21. read stopbit starting edge high

  22. busy waiting 1 bit time -0.21 milli second

  23. Interrupt is now re-enabled

So the machine is running with interrupt disabled for 2.1 milli second.

SW based TX or RX - you decide

Some thoughts.

  • Above we see that bit banging with interrupt is disabled is user for TX and RX.

  • So at a given time only RX or TX can take place.

  • Furthermore interrupt disabled for such long time may have negative impact on HW (and of course SW as well) devices.

An exanple.

  1. On HW UART a GPS running 9600 baud is running

  2. On a SoftwareSerial port running 1200 baud we have a comm link to another machine

Receiving 1 byte @ 1200 baud at th SW UARTS disables interupt for 10 milliseconds

The HW UART for the GPS takes 1.25 millisecond for each byte

10/1.25 = 8 has the potential that we loose 8 bytes in a row from the GPS.

hmmm

SW TX has normally no outgoing buffer because it is bitbang driven TX carried out by the caller of the write command.

Final thoughts

IF your are strictly servicing one SW and HW based system at a time it might work.

For data and CPU time budget you have - of course - to take bit banging/pulling time into your budget.

Doing bitbanging in a kernel based system is not recommended.

At 1200 baud interrupt will be disabled 10 milliseconds which is 10 kernel tick.

BTW your millis counter or similar will also loose time.

In a multicore system you might locate bit banging on one core and essential realtime task on other(s)) core. This might add RT quality to your solution.