I am still learning XC and want to utilize established "software design patterns" or best practices wherever possible.
I was looking at the UART (Part 2) in "Programming XC on XMOS Devices". I have the UART running in a thread by itself. Assume the UART is a slow bit rate for this example.
I have another thread that wants to use the UART. I replaced the putByte() function call with a channel. That works really well.
What is the best way to handle the tx portion of the problem? Say the other thread wants to send out a couple dozen bytes with the UART thread. My first thought was to use a another channel, but what is the best wat to do that? Should I send the bytes one at a time through the channel? This would require a char array buffer in the UART thread. That's OK, but seems a little messy and slow waiting for each channel transaction. Should I use a streaming channel? The book briefly mentions the "channel buffer", but I could find no reference to the size of the buffer.
It would handy if someone could expand the UART example to show this. Something like a PC master/ XMOS slave example. The PC sends a dozen bytes, then the XMOS sends them back.
Basic UART Question
Below is what I have now. It works fine, but the multiple channel hits right in a row does not like the idea solution. I never have more than about 6 bytes to send at a time...that helps.
I found that the data being streamed must not be "sub word size input". I still don't know the buffer depth.
I found that the data being streamed must not be "sub word size input". I still don't know the buffer depth.
Code: Select all
/* Steaming small amount of data to UART tx
* Untested "psuedo" code for discussion purposes only
*
*
*
*/
#include <xs1.h>
#define TMR_SPEED 100000000 // 100MHz XMOS System Timer
// for the UART
#define BIT_RATE 57600
#define BIT_TIME TMR_SPEED / BIT_RATE
#define BUFF_LEN 30
// port assignments
in port uartRx = XS1_PORT_1C; // Pin XD10
out port uartTx = XS1_PORT_1D; // Pin XD11
// function prototypes
void UART ( in port RX , int rxPeriod , out port TX , int txPeriod, chanend rxChar, streaming chanend txChar);
void commCenter(chanend rxChar, streaming chanend txChar);
int main() {
chan rxChar;
streaming chan txChar;
// the following items run on parallel threads
par
{
UART(uartRx, BIT_TIME, uartTx, BIT_TIME, rxChar, txChar);
commCenter(rxChar, txChar);
}
while(1)
;
return 0;
}
/*most of this is a direct copy from "Programming XC on XMOS Devices UART (Part 2)"
*
*/
void UART ( in port RX , int rxPeriod , out port TX , int txPeriod, chanend rxChar, streaming chanend txChar ) {
int txByte , rxByte ;
int txI , rxI;
int rxTime , txTime ;
int isTX = 0;
int isRX = 0;
char rxData;
unsigned char txData;
timer tmrTX , tmrRX ;
// setup a FIFO buffer for the transmit buffer
char txFifoBuf[BUFF_LEN];
unsigned int txFifoRead = 0, txFifoWrite = 0;
while (1)
{
if (! isTX && (txFifoRead != txFifoWrite) ) {
isTX = 1;
txI = 0;
txByte = txFifoBuf[txFifoRead];
txFifoRead = (txFifoRead + 1) % BUFF_LEN; // incr the read point or rollover to 0
TX <: 0; // transmit start bit
tmrTX :> txTime ; // set timeout for data bit
txTime += txPeriod ;
}
select {
case ! isRX => RX when pinseq (0) :> void :
isRX = 1;
tmrRX :> rxTime ;
rxI = 0;
rxTime += rxPeriod ;
break ;
case isRX => tmrRX when timerafter ( rxTime ) :> void :
if ( rxI < 8)
RX :> >> rxByte ;
else { // receive stop bit
RX :> void ;
//putByte ( rxByte >> 24);
rxData = (rxByte >> 24);
rxChar <: rxData;
isRX = 0;
}
rxI ++;
rxTime += rxPeriod ;
break ;
case isTX => tmrTX when timerafter ( txTime ) :> void :
if ( txI < 8)
TX <: >> txByte ;
else if (txI == 8)
TX <: 1; // stop bit
else
isTX = 0;
txI ++;
txTime += txPeriod ;
break ;
case txChar :> txData : // We got a character from the UART via the channel
txFifoBuf[txFifoWrite] = (unsigned char)txData;
txFifoWrite = (txFifoWrite + 1) % BUFF_LEN; // incr or rollover to 0
break;
}
}
}
void commCenter(chanend rxChar, streaming chanend txChar)
{
char rx;
int cntr = 0;
while(1){
select {
case rxChar :> rx : // We got a character from the UART via the channel
if (cntr++ == 5) // count to five then send and reset counter
{
// stream out the command
txChar <: 1;
txChar <: 2;
txChar <: 3;
txChar <: 4;
txChar <: 5;
cntr = 0;
}
break;
}
}
}