Attention. Somewhat long post ahead ;)
I try to send "lengthy" datapackets (~80 - 1500 Bytes) over Software UART between two XC boards.
Right now I use the following functions for sending and receiving:
Code: Select all
/** UART receive a character
**/
unsigned char uart_getch()
{
unsigned data = 0, time;
int i;
unsigned char buffer;
UART_RX_PORT when pinseq( 0) :> int _ @ time;
time += bit_time + (bit_time >> 1);
// sample each bit in the middle.
for (i = 0; i < 8; i += 1)
{
UART_RX_PORT @ time :> >> data;
time += bit_time;
}
// reshuffle the data.
buffer = (unsigned char) (data >> 24);
return buffer;
}
Code: Select all
/** UART transmit a character.
* This is blocking call for now.
*/
void uart_putch(unsigned char buffer)
{
unsigned time, data;
data = buffer;
// get current time from port with force out.
UART_TX_PORT <: 1 @ time;
// Start bit.
UART_TX_PORT <: 0;
// Data bits.
for (int i = 0; i < 8; i += 1)
{
time += bit_time;
UART_TX_PORT @ time <: >> data;
}
// Stop bit
time += bit_time;
UART_TX_PORT @ time <: 1;
time += bit_time;
UART_TX_PORT @ time <: 1;
}
I can't use XON/XOFF because these packets are in binary and can contain any value in its bytes.
As my putch-function doesn't care about external pin values, it transmits even if there is no recipient. The getch-function has to wait for the start bit, while blocking the thread till a start bit occurs.
While sending without a care, I can't make sure that my data is received or if the supposed receiver is even ready to receive and my whole thread could hang, waiting for the response to a command that was never received at the other end.(busy, turned off,...)
Turning on the module that is receiving the packets via UART first is fine, as it is waiting for the start bit condition to occour. Turning on the UART-"sender" second is fine too, as it happily outputs its commands and waits for the responses of the "receiver".
The other way around is not looking quite as fine. The sender is turned on and starts to send and waits till the end of life, the universe and everything, because the receiver never got the command and doesn't know what to do and decides to wait for the command it already missed and won't be sent again because there was no response to it yet.
So the obvious solution is to use a timer and implement some timeout handling. Timer work fine in selects, waiting for channel communications.
So using something like
Code: Select all
select
{
case temp = uart_getch():
// something
break;
case tmr when timerafter(timeoutx) :> int:
// some other thing
break;
}
The only other way i can think of right now is to somehow return from my uart_getch() function and checking if a timeout occured, using a timer while waiting for the start bit to go low.
Sorry for all the rambling, seems the wheather got to my and i can't get this out of my head.
Dave