mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 19:30:36 +02:00
119 lines
3.6 KiB
Plaintext
119 lines
3.6 KiB
Plaintext
|
libubb: SWUART - a software-implemented UART
|
||
|
============================================
|
||
|
|
||
|
libubb also provides a UART implemented in software. This UART uses
|
||
|
signals of UBB and runs in user space.
|
||
|
|
||
|
To comply with the relatively tight bit timing requirements of the
|
||
|
serial protocol, the UART's transfer function disables interrupts
|
||
|
while sending or receiving data, and it uses hardware timer 7.
|
||
|
|
||
|
The format is always 8 data bits, no parity, one stop bit.
|
||
|
|
||
|
|
||
|
Installation, compiling, and linking
|
||
|
------------------------------------
|
||
|
|
||
|
Compiler and linker settings are the same as for general use of
|
||
|
UBB.
|
||
|
|
||
|
|
||
|
Skeleton program
|
||
|
----------------
|
||
|
|
||
|
This program fragment illustrates the key elements the SWUART:
|
||
|
|
||
|
1 #include <ubb/ubb.h>
|
||
|
2 #include <ubb/swuart.h>
|
||
|
3
|
||
|
4 ...
|
||
|
5 #define TX UBB_DAT0
|
||
|
6 #define RX UBB_DAT1
|
||
|
7 ...
|
||
|
8
|
||
|
9 char buf[200];
|
||
|
10 int got;
|
||
|
11
|
||
|
12 if (ubb_open(0) < 0) {
|
||
|
13 perror("ubb_open");
|
||
|
14 exit(1);
|
||
|
15 }
|
||
|
16
|
||
|
17 if (swuart_open(TX, RX, 38400) < 0) {
|
||
|
18 perror("swuart_open");
|
||
|
19 exit(1);
|
||
|
20 }
|
||
|
21
|
||
|
22 got = swuart_trx("hello\n", 6, buf, sizeof(buf), 40000, 20000);
|
||
|
23 fwrite(buf, 1, got, stdout);
|
||
|
24
|
||
|
25 swuart_close();
|
||
|
26 ubb_close(0);
|
||
|
|
||
|
Until line 15 we have the usual UBB setup, with the difference that
|
||
|
we also include ubb/swuart.h
|
||
|
|
||
|
Note that we don't call ubb_power in this example. If power has to
|
||
|
be supplied to the device connected to UBB, such a call would have
|
||
|
to be made.
|
||
|
|
||
|
Lines 17 to 19 prepare the UART. TX and RX are the bits used to send
|
||
|
or receive, respectively. If sending or receiving is not needed, set
|
||
|
the respective value to zero. The bit rate should be in the range
|
||
|
from 110 to 115200.
|
||
|
|
||
|
swuart_open return 0 on success. In case of an error, it returns a
|
||
|
negative value and sets "errno".
|
||
|
|
||
|
The call to swuart_trx in line 22 is the heart of SWUART: it first
|
||
|
sends the six bytes of "hello\n" and then wait for up to 40000 bit
|
||
|
times (i.e., about one second) for a response. The response is assume
|
||
|
to have ended once 20000 bit times (about half a second) have passed
|
||
|
since the last time a byte has been successfully received and stored.
|
||
|
|
||
|
swuart_trx returns the number of bytes that have been received. If
|
||
|
there was no response, it returns 0.
|
||
|
|
||
|
Line 23 writes anything that has been received to standard output.
|
||
|
|
||
|
Lines 25 and 26 shut down everything. It is not necessary to call
|
||
|
swuart_close if the process simply exits.
|
||
|
|
||
|
|
||
|
Errors
|
||
|
------
|
||
|
|
||
|
The functions swuart_get_errors and swuart_clear_errors access the
|
||
|
receiver error counters. See include/ubb/swuart.h for details.
|
||
|
|
||
|
The following error conditions are detected:
|
||
|
|
||
|
- glitch: any falling edges that look like a start bit but where
|
||
|
the signal returns to "1" in the middle of the bit. The receiver
|
||
|
does not try to receive the rest of such a byte.
|
||
|
|
||
|
- framing: bytes with a stop bit that is not "1". Such bytes are
|
||
|
discarded.
|
||
|
|
||
|
- overflow: bytes received when the buffer is already full.
|
||
|
Reception of data when the buffer is full will not restart the
|
||
|
idle timeout but swuart_trx will still wait for the specified
|
||
|
amount of time to pass.
|
||
|
|
||
|
|
||
|
Duplex limitations
|
||
|
------------------
|
||
|
|
||
|
While a reception can start while swuart_trx is still sending and
|
||
|
the bit boundaries of sender and receiver do not need to coincide,
|
||
|
this still isn't entirely full-duplex.
|
||
|
|
||
|
For example, data arriving before the first call to swuart_trx or
|
||
|
between calls to swuart_trx is lost. If swuart_trx is invoked
|
||
|
while data is arriving, it may misinterpret data bits as start
|
||
|
bits and thus receive garbage.
|
||
|
|
||
|
Furthermore, swuart_trx disables interrupts while running. This
|
||
|
means that the entire Ben will be unresponsive during that time.
|
||
|
Therefore, the idle intervals should be as short as possible.
|