- Rx/Tx UART access
ADC acquisition via SPI
Storing samples in a FIFO
Supplying a console user interface to configure the device
I think my best bet is to create a "controller" thread that uses channels to communicate with threads that take care of these other tasks and can implement the executive/console portion.
I want to be able to write a controller which can implement the command console by interacting with the rx and tx threads, pulling information as directed from the FIFO or acquisition threads, configuring things like the sample rate in the acquisition thread by sending configuration commands to it via the channel.
If there is receive data, I need to be able to respond to it almost immediately and potentially interrupt the transmission of other data in the transmit thread. It seemed like a select statement would be a natural choice, but I'm finding that if there's a lot of channel data for one of the select cases, the others never get a chance to run. Seems this select channel structure will either block or starve others.
I'm looking for suggestions or examples on how to best structure code to integrate tasks like this.
Here's the skeleton of what I have (minus implementation specific code ) - just the basic parallelism and channel arrangement I've been experimenting with so you get the idea of what I'm trying to do.
Code: Select all
/* channel-test.xc
* experiment with how channels work
* attempt to create a master controller which communicates via channels
* to all other threads
*/
#include <xs1.h>
#include <print.h>
#include <platform.h>
#include <xclib.h>
#include <string.h>
#include "xfifo.h"
#define FIFO_SIZE (11 * 1024)
void acquire(chanend controllerChan )
{
while( 1 )
{
controllerChan <: 5; // dummy data
printstrln("Acquire putting 5 into acq channel");
}
}
void rx(chanend controllerChan )
{
while( 1 )
{
//controllerChan <: (int)'a'; // dummy data
//printstrln("Rx Putting 'a' into receive channel");
}
}
void tx(chanend controllerChan )
{
unsigned int txData;
while( 1 )
{
controllerChan <: txData ; // get data from channel to send out
printstrln("Tx Got data to transmit");
}
}
void monitor_fifo(chanend controllerChan )
{
while( 1 )
{
controllerChan <: 1; // dummy
printstrln("Fifo monitor Put 1 into fifo control channel");
}
}
void controller(chanend rxChan, chanend txChan, chanend acqChan, chanend fifoChan )
{
unsigned int rxData, txData, acqData, fifoData;
txData = 100;
while( 1 )
{
select {
case rxChan :> rxData :
// do something with rxData
printstrln("Rx Data received");
break;
case acqChan :> acqData :
// do something related to data acquired
printstrln("Acq Data received");
break;
case fifoChan :> fifoData :
// do something with fifoData received
printstrln("Fifo Data received");
break;
}
// default
if ( txData != 0x00 )
{
printstrln( "Putting 100 into Tx channel");
txChan :> txData;
// change some status related to tx data
printstrln( "Put 100 into Tx channel");
}
}
}
unsigned int fifobuf[FIFO_OVERHEAD + FIFO_SIZE];
int main()
{
chan rxChan, txChan, acqChan, fifoChan;
xfifo_t fifo;
fifo = xfifo_init( fifobuf, FIFO_SIZE);
par {
controller( rxChan, txChan, acqChan, fifoChan );
monitor_fifo(fifoChan);
acquire(acqChan);
rx(rxChan);
tx(txChan);
}
return 0; // should never get here
}
I hope this isn't too general a question, but if so, I'd like to focus on how to create an executive loop that can check multiple channels data/status without getting blocked - would be nice to see something like a channel peek() - I could be missing something key.
Thanks for any tips,
Landon