Basic UART Question

Technical questions regarding the xTIMEcomposer, xSOFTip Explorer and Programming with XMOS.
User avatar
bdring
Member
Posts: 13
Joined: Tue Dec 22, 2009 2:33 pm

Basic UART Question

Postby bdring » Tue Dec 22, 2009 3:09 pm

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.
User avatar
bdring
Member
Posts: 13
Joined: Tue Dec 22, 2009 2:33 pm

Postby bdring » Wed Dec 23, 2009 7:59 pm

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.

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;			
		}
	}
}

Who is online

Users browsing this forum: No registered users and 2 guests