The primary target hardware for weAutSys — the automation controller weAut_01 — can use AVR's UART0 for serial (V.24 / RS232) communication with optional RTS and/or CTS flow control.
Driver software (see module serial I/O) and system initialisation may bind stdin, stdout and stderr to this serial link. So these streams and all their format string controlled formatting and parsing are available. But these are expensive functions (partly using many 100 µs µController time) and not well suited to weAutSys' non preemptive nature. Hence using the (non blocking) UART and stdI/O functions as well as the formatters and parsers provided here is strongly recommended (en lieu de stdio.h).
As best fit for weAutSys' non preemptive Protothreads approach status functions are provided. They can be used in boolean expressions for Protothreads' blocking and yielding operations:
PT_WAIT_ASYIELD_WHILE(pt, outSpace(stdout) < 120); printf("Hello, world!\n"); // never use printf embedded
or better:
INFLASH(char hellWo[]) = "Hello, world! \n"; // 0123456789.1234 5 : : : : : : : PT_YIELD_OUT_SPACE(pt, 15); stdPutS_P(hellWo);
Files | |
file | uart0.h |
Serial communication (basics) | |
Defines | |
#define | UART_IN_BUF_CAP 127 |
The maximum capacity of the serial input buffer. | |
#define | UART_IN_SPACE_LIM 11 |
UART space limit for flow control. | |
#define | UART_OUT_BUF_CAP 255 |
The capacity of the serial output buffer. | |
Functions | |
uint16_t | serInBufferd (FILE *streams) |
The number of characters buffered from serial input. | |
void | setUARTflowcontrolByChar (char cC) |
Sets UART flow control by (one) character. | |
uint8_t | uartClearInBuffer (void) |
Clear the internal buffer for serial input. | |
int | uartGetChar (FILE *stream) |
Get one byte from serial input. | |
uint8_t | uartGetLine (char *line, uint8_t max) |
Read a line from UART. | |
uint8_t | uartInBufferd (void) |
The number of characters buffered from serial input. | |
uint8_t | uartInErrors (void) |
The accumulated serial input (UART0) errors. | |
uint8_t | uartInRetBufferd (void) |
The number of line feeds buffered from serial input. | |
uint8_t | uartOutSpace (void) |
The buffer space available for serial output. | |
uint8_t | uartPutBytes (uint8_t *src, uint8_t n) |
Put some bytes (characters) to serial output. | |
uint8_t | uartPutChars (char *src, uint8_t n) |
Put some characters to serial output. | |
int | uartPutCharsP (char const *src, uint8_t n) |
Put some characters from program space to serial output. | |
uint8_t | uartPutSt (char *src, const FILE *stream) |
Put a RAM string (some characters) to serial output. | |
int | uartPutSt_P (prog_char *src, const FILE *stream) |
Put a string (some characters) from flash memory to serial output. | |
Variables | |
uint8_t | uartInAccErrors |
The serial input's accumulated (or) errors. | |
uint8_t | uartInBufRetCnt |
The serial input buffer line feeds code counter. |
#define UART_OUT_BUF_CAP 255 |
The capacity of the serial output buffer.
The value must be 2**n-1 and fit into an unsigned byte.
Possible values are 15, 31, 63, 127 and 255.
Recommended (default) is 255. This is a good compromise concerning RAM saving and avoiding thread waits / yields due to buffer fill. Use lower values only if the RAM is urgently needed.
The capacity's upper limit (255) is fixed by the type (uint8_t) chosen for lengths and indices. This makes most respective operations more than twice as fast as would be with 16 bit types (uint16_t). If larger UART buffers should become necessary that could be changed on customer request. As an alternative using higher baud rates should be considered. At (default) 38400 it takes 67 ms to empty (send) a 256 byte buffer. That is reduced to 22ms with 115K2. Sending more than 100 characters over the UART (every time) in the 10 ms thread (or 23 at 38400) would fail anyway in the long run, no matter the buffer size. Consider Ethernet communication (probably utilising the Telnet) as alternative.
#define UART_IN_BUF_CAP 127 |
The maximum capacity of the serial input buffer.
The value must be 2**n-1 and fit into an unsigned byte.
Possible values are 15, 31, 63, 127 and 255.
Recommended (default) is 127 that is fit for terminal command lines.
It may be set to to 255 if RAM is available. For still larger buffer sizes compare the remarks about the output buffer capacity. If input size is critical input flow control is the recommended means to put the buffer burden to the sender.
#define UART_IN_SPACE_LIM 11 |
uint8_t uartOutSpace | ( | void | ) |
The buffer space available for serial output.
This function returns the number of bytes that can be output UART output by serPutChar() e.g. without loosing data.
The returned value is in the range 0 ..UART_OUT_BUF_CAP - 1.
If 0 is returned nothing should be output.
uint8_t uartPutChars | ( | char * | src, |
uint8_t | n | ||
) |
Put some characters to serial output.
This function never blocks. It returns the number of characters transferred. If not enough space is available the returned value will be smaller than n
or than the length of the string src
. It may even be 0. In the latter case nothing was output.
Hence this operation should be (indirectly) guarded by uartOutSpace().
The output stops after n characters or at the first 0 in src. By that this is a string output function. To send a (binary) 0 use serPutChar(char c, ...) or uartPutBytes().
src | the characters to be output (not NULL !) |
n | the maximum number of characters to be output |
uint8_t uartPutBytes | ( | uint8_t * | src, |
uint8_t | n | ||
) |
Put some bytes (characters) to serial output.
This function never blocks. It returns the number of bytes transferred. If not enough space is available the returned value will be smaller than n
. It may even be 0. In the latter case nothing was output.
Hence this operation should be (indirectly) guarded by uartOutSpace().
src | the characters to be output |
n | the maximum number of characters to be output |
uint8_t uartPutSt | ( | char * | src, |
const FILE * | stream | ||
) |
Put a RAM string (some characters) to serial output.
This function never blocks. It returns the number of characters transferred. If not enough space is available the returned value will be smaller the length of the string src
. It may even be 0. In the latter case nothing was output.
Hence this operation should be (indirectly) guarded by uartOutSpace().
The output stops after n characters or at the first 0 in src. By that this is a string output function. To send a (binary) 0 use serPutChar(char c, ...).
Hint: The parameter stream is not used in the present (June 2012) implementation, but should be set correctly in case of future changes.
src | the characters to be output |
stream | the serial output as stream |
int uartPutSt_P | ( | prog_char * | src, |
const FILE * | stream | ||
) |
Put a string (some characters) from flash memory to serial output.
This function never blocks. It returns the number of characters transferred. If not enough space is available the returned value will be smaller the length of the string src
. It may even be 0. In the latter case nothing was output.
Hence this operation should be (indirectly) guarded by uartOutSpace().
The output stops after n characters or at the first 0 in src. By that this is a string output function. To send a (binary) 0 use serPutChar(char c, ...).
Hint: The parameter stream is not used in the present (June 2012) implementation, but should be set correctly in case of future changes.
src | the characters to be output |
stream | the serial output as stream |
int uartPutCharsP | ( | char const * | src, |
uint8_t | n | ||
) |
Put some characters from program space to serial output.
This function never blocks. It returns the number of characters transferred. If not enough space is available the returned value will be smaller than n
or the length of the string src
. It may even be 0. In the latter case nothing was output.
Hence this operation should be (indirectly) guarded by uartOutSpace().
The output stops after n characters or at the first 0 in src.
src | the characters to be output in flash memory (not NULL !) |
n | the maximum number of characters to be output |
int uartGetChar | ( | FILE * | stream | ) |
Get one byte from serial input.
This function never blocks. It returns a byte value read or EOF.
Hence this operation should be (indirectly) guarded by uartInBufferd().
stream | (passed by stdio input) totally ignored by this function |
uint8_t uartInBufferd | ( | void | ) |
The number of characters buffered from serial input.
This function returns the number of bytes that can be fetched from serial input by uartGetChar(FILE*) without getting EOF.
The returned value is in the range 0 .. UART_IN_BUF_CAP - 1. If 0 is returned nothing should be read. If UART_IN_BUF_CAP is returned the internal buffer was overrun and the input data are incomplete respectively corrupt.
uint16_t serInBufferd | ( | FILE * | streams | ) |
The number of characters buffered from serial input.
Same as uartInBufferd (other respectively common signature).
uint8_t uartInRetBufferd | ( | void | ) |
The number of line feeds buffered from serial input.
This function gives the number of line feeds, i.e. LF
or CR
chars that were read from serial input and not yet fetched from buffer by uartGetChar(FILE*) or uartGetLine(char[], int).
The returned value is in the range 0 .. UART_IN_BUF_CAP . If 0 is returned no (stdio) function expecting a complete line input should be called.
uint8_t uartInErrors | ( | void | ) |
The accumulated serial input (UART0) errors.
This function returns all UART 0 input errors accumulated (ORed) in the past:
Bit 6: buffer overrun. More than UART_IN_BUF_CAP bytes were received but not fetched in due time.
Bit 4: framing error. This usually happens if the two UARTs connected do not have the same setting, one of their clocks are out of tolerance, hardware noise or connector troubles.
Bit 3: UART buffer overrun. This should not happen, the effect of slow input processing is Bit 6. If this happens, some interrupt handlers or (atomic) critical sections block interrupts too long.
Bit 2: Parity error. This has often the same causes as bit 4. Can only happen with parity enabled.
If this function returns 0 all was well since last call or last buffer clearance. A call to this function resets the errors.
uint8_t uartClearInBuffer | ( | void | ) |
Clear the internal buffer for serial input.
This function returns the number of characters forgotten. If 0 is returned the buffer was empty anyway.
This function is to be used to recover from buffer overrun or similar errors or to "forget the past" out of any other reasons.
uint8_t uartGetLine | ( | char * | line, |
uint8_t | max | ||
) |
Read a line from UART.
This function will copy all characters to the array (line
) supplied ending with line feed. This line feed may be one or two characters LF or CR; it will be put as one ending 0 as last character into line.
Returned is the number of characters copied to the array line
. This might be 0; it will never be more than max
, uartInRetBufferd() and UART_IN_BUF_CAP.
A full line was got if the last character ([returned value -1]) is (char) 0 which will, as said, replace the terminating line feed form the (buffered) input. So, space permitting, the modified line
[] will be a null-terminated (C-) string.
To guarantee a full line, a call to this function should be guarded by uartInRetBufferd() and max better be >= UART_IN_BUF_CAP.
line | the character array to put the received line to |
max | the maximum number of characters transferred |
void setUARTflowcontrolByChar | ( | char | cC | ) |
Sets UART flow control by (one) character.
i c: input flow control by CTS
o r: output flow control by RTS
b : both CTS and RTS n, all else: no flow control
cC | the controlling character (may also be in upper case) |
uint8_t uartInAccErrors |
The serial input's accumulated (or) errors.
If 0 no errors had occurred since last check.
Bit 4 set: at least one framing error had occurred.
Bit 3 set: at least one overrun error had occured.
Bit 2 set: at least one parity error had occurred.
Bit 6 set: at least one byte could not be put to buffer.
Bit 5 set: at least one spike was ignored.