[Tinyos-beta-commits] CVS: tinyos-1.x/beta/platform/imote2
BulkTxRx.nc, NONE, 1.1 HPLSSP.nc, NONE, 1.1 HPLSSP1M.nc, NONE,
1.1 SingleTxRx.nc, NONE, 1.1 SSP.nc, NONE, 1.1 SSP1C.nc, NONE,
1.1 SSP1M.nc, NONE, 1.1
Robbie Adler
radler at users.sourceforge.net
Mon Jul 25 18:36:09 PDT 2005
Update of /cvsroot/tinyos/tinyos-1.x/beta/platform/imote2
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26508
Added Files:
BulkTxRx.nc HPLSSP.nc HPLSSP1M.nc SingleTxRx.nc SSP.nc
SSP1C.nc SSP1M.nc
Log Message:
Initial checkin of SSP port functionality with an attempt to follow the TOS 2.0 platform HPL->HAL->HIL model.
--- NEW FILE: BulkTxRx.nc ---
/**
* The HPLDMA interface is intended to provide the functionality of a DMA
* controller on both the send and receive sides of a transaction. In order
* to provide this functionality, the interface provide 2 commands and 2
* events. Because the DMA interface is intended to supplement a standard
* byte based interface, there is no init, start, or stop. Instead
* either of the 2 commands may return fail if for some reason there is
* something wrong with port when the command is issued
*
* @author Robbie Adler
**/
interface BulkTxRx {
/**
* Begin a BulkReceive. The parameters should be the initial buffer
* to place data into and the inital number of bytes. DMA receive chaining
* may be accomplished by returning a new buffer in the associated DMAGetDone
* event. Return NULL to complete the DMA transaction.
**/
command result_t BulkReceive(uint8_t *RxBuffer, uint16_t NumBytes) ;
/**
* This command informs the component to send NumBytes
* using the TxBuffer parameter as the source.
**/
command result_t BulkTransmit(uint8_t *TxBuffer, uint16_t NumBytes) ;
/**
* This event is signaled to inform the application that NumBytes
* have been received. No assumptions can be made about the
* contents of the RxBuffer once this event returns. If the caller
* wants to hold onto these bytes, it should save a copy of it. To
* chain receives OF THE SAME LENGTH together, return a new buffer from this
* event. If a new transaction of a different length is required or if
* the application is done receiving data, return NULL and trigger the new
* transaction from outside this event. If for some reason
* the hardware was unable to capture NumBytes of contiguous data without
* an overrun condition occuring, the event will be signaled with NumBytes 0.
* In this case, the data pointer will be valid so as to allow the
* application to free the memory associated with the original get request.
*
**/
event uint8_t *BulkReceiveDone(uint8_t *data, uint16_t NumBytes);
/**
* This event is signaled by the component to indicate
* that the bytes have been sent out.
**/
event result_t BulkTransmitDone(uint8_t *data);
}
--- NEW FILE: HPLSSP.nc ---
/**
*@author Robbie Adler
**/
//#include "SSP.H"
interface HPLSSP{
//configuration routines
#if 0
async command result_t init(); //generic command to configure things the way we defintiely need.
async command result_t setSSPFormat(SSPFrameFormat_t format);
async command result_t setDataWidth(SSPDataWidth_t width);
async command result_t enableInvertedSFRM(bool enable);
async command result_t setRxFifoLevel(SSPFifoLevel_t level);
async command result_t setTxFifoLevel(SSPFifoLevel_t level);
async command result_t setMicrowireTxSize(SSPMicrowireTxSize_t size);
//clk specific configuration routines
async command result_t setClkRate(uint16_t clkdivider);
async command result_t setClkMode(SSPClkMode_t);
//interrupt manipulation routines
//DMA driven
async command result_t enableTxDMAInterrupt();
async command result_t disableTxDMAInterrupt();
async command result_t enableRxDMAInterrupt();
async command result_t disableRxDMAInterrupt();
//Processor driven
async command result_t enableTxInterrupt();
async command result_t disableTxInterrupt();
async command result_t enableRxInterrupt();
async command result_t disableRxInterrupt();
//generic
async command result_t enableRxTimeOutInterrupt();
async command result_t disableRxTimeOutInterrupt();
async command result_t enableTrailingByteInterrupt();
async command result_t disableTrailingByteInterrupt();
//port behavior routines
async command result_t enablePort(bool enable);
async command result_t enableTxTristate(bool enable);
async command result_t enableClkMaster(bool enable);
async command result_t enableSFRMMaster(bool enable);
async command result_t enableRxWithoutTx(bool enable);
async command result_t enableFreeRunningSlaveClk(bool enable);
async command result_t enableTrailingBytes(bool processorhandles);
async command result_t setSCLKPhase(SSPSCLKPhase_t clkphase);
async command result_t setSCLKPolarity(SSPSCLKPolarity_t clkpolarity);
//test routines
async command result_t enableTestFIFOMode(bool enable);
async command result_t setTestModeFIFO(SSPTestModeFIFO_t whichFifo);
async command result_t enableLoopBack(bool enable);
#endif
async command result_t setSSCR0(uint32_t newVal);
async command uint32_t getSSCR0();
async command result_t setSSCR1(uint32_t newVal);
async command uint32_t getSSCR1();
async command result_t setSSPSP(uint32_t newVal);
async command uint32_t getSSPSP();
async command result_t setSSTO(uint32_t newVal);
async command uint32_t getSSTO();
async command result_t setSSITR(uint32_t newVal);
async command uint32_t getSSITR();
async command result_t setSSSR(uint32_t newVal);
async command uint32_t getSSSR();
async command result_t setSSDR(uint32_t newVal);
async command uint32_t getSSDR();
}
--- NEW FILE: HPLSSP1M.nc ---
//@author Robbie Adler
module HPLSSP1M {
provides {
interface HPLSSP;
}
}
implementation {
//we are SSP1...do some #defining to make things easier in the future
#define _SSCR0 SSCR0_1
#define _SSCR1 SSCR1_1
#define _SSPSP SSPSP_1
#define _SSTO SSTO_1
#define _SSITR SSITR_1
#define _SSSR SSSR_1
#define _SSDR SSDR_1
async command result_t HPLSSP.setSSCR0(uint32_t newVal){
atomic{
_SSCR0 = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSCR0(){
uint32_t temp;
atomic{
temp = _SSCR0;
}
return temp;
}
async command result_t HPLSSP.setSSCR1(uint32_t newVal){
atomic{
_SSCR1 = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSCR1(){
uint32_t temp;
atomic{
temp = _SSCR1;
}
return temp;
}
async command result_t HPLSSP.setSSPSP(uint32_t newVal){
atomic{
_SSPSP = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSPSP(){
uint32_t temp;
atomic{
temp = _SSPSP;
}
return temp;
}
async command result_t HPLSSP.setSSTO(uint32_t newVal){
atomic{
_SSTO = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSTO(){
uint32_t temp;
atomic{
temp = _SSCR1;
}
return temp;
}
async command result_t HPLSSP.setSSITR(uint32_t newVal){
atomic{
_SSITR = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSITR(){
uint32_t temp;
atomic{
temp = _SSITR;
}
return temp;
}
async command result_t HPLSSP.setSSSR(uint32_t newVal){
atomic{
_SSSR = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSSR(){
uint32_t temp;
atomic{
temp = _SSSR;
}
return temp;
}
async command result_t HPLSSP.setSSDR(uint32_t newVal){
atomic{
_SSDR = newVal;
}
return SUCCESS;
}
async command uint32_t HPLSSP.getSSDR(){
uint32_t temp;
atomic{
temp = _SSDR;
}
return temp;
}
}
--- NEW FILE: SingleTxRx.nc ---
/**
* SingleTxRx interface is intended to provide the generic functionality
* of a single sample receive or transmit. The receive model requres that
* a user first issue a request to receive data (startReceive). Successive
* received samples will be indicated by a receiveDone event. A user may
* at any time issue a stopReceive command.
*
* @author Robbie Adler
**/
interface SingleTxRx {
/**
*
* Begin a single sample at a time Receive. a receiveDone event will be
* generated everytime a sample is received
*
**/
command result_t startReceive() ;
/**
* Stops a single sample at a time received.
*
**/
command result_t stopReceive() ;
/**
* This command informs the component to send a sample
*
**/
command result_t transmit(uint32_t sample) ;
/**
*
* event to indicate the reception a sample
*
**/
event result_t receiveDone(uint32_t data);
/**
*
* event to indcate that a transmit sample operation has been completed
*
**/
event result_t transmitDone();
}
--- NEW FILE: SSP.nc ---
/**
*@author Robbie Adler
**/
includes SSP; //this will need to change to #include SSP in the future
interface SSP{
command result_t init(); //generic command to configure things the way we defintiely need.
command result_t setSSPFormat(SSPFrameFormat_t format);
command result_t setDataWidth(SSPDataWidth_t width);
command result_t enableInvertedSFRM(bool enable);
command result_t setRxFifoLevel(SSPFifoLevel_t level);
command result_t setTxFifoLevel(SSPFifoLevel_t level);
command result_t setMicrowireTxSize(SSPMicrowireTxSize_t size);
//clk specific configuration routines
command result_t setClkRate(uint16_t clkdivider);
command result_t setClkMode(SSPClkMode_t);
//master vs slave configuration routines
command result_t setMasterSCLK(bool enable);
command result_t setMasterSFRM(bool enable);
command result_t setReceiveWithoutTransmit(bool enable);
}
--- NEW FILE: SSP1C.nc ---
//@author Robbie Adler
configuration SSP1C{
provides{
interface BulkTxRx;
interface SingleTxRx;
interface SSP;
}
}
implementation{
components SSP1M,
HPLSSP1M,
PXA27XInterruptM;
BulkTxRx=SSP1M.BulkTxRx;
SingleTxRx=SSP1M.SingleTxRx;
SSP=SSP1M.SSP;
SSP1M.HPLSSP->HPLSSP1M;
SSP1M.SSPInterrupt -> PXA27XInterruptM.PXA27XIrq[PPID_SSP1];
}
--- NEW FILE: SSP1M.nc ---
//@author Robbie Adler
module SSP1M {
provides {
interface BulkTxRx;
interface SingleTxRx;
interface SSP;
}
uses {
interface HPLSSP;
interface PXA27XInterrupt as SSPInterrupt;
}
}
implementation {
SSPFrameFormat_t gFrameFormat;
SSPDataWidth_t gDataWidth;
bool gEnableInvertedSFRM;
SSPFifoLevel_t gRxFifoLevel;
SSPFifoLevel_t gTxFifoLevel;
SSPMicrowireTxSize_t gMicrowireSize;
uint16_t gClkdivider;
SSPClkMode_t gClkMode;
bool gSlaveClockFreeRunning;
bool gMasterSCLK;
bool gMasterSFRM;
bool gReceiveWithoutTransmit;
bool gRxFifoOverrun;
bool gAudioClockSelect;
bool gRxInProgress;
bool gTxInProgress;
norace uint16_t gNumRxFifoOverruns;
norace uint8_t *gRxBuffer;
norace uint16_t gRxNumBytes, gRxBufferPos;
uint32_t createSSCR0();
uint32_t createSSCR1();
command result_t SSP.init(){
uint32_t SSCR0, SSCR1;
//reinitialize global state to allow for reentrancy
gFrameFormat = SSP_SSP;
gDataWidth= SSP_16bits;
gEnableInvertedSFRM= TRUE;
gRxFifoLevel = SSP_8Samples;
gTxFifoLevel = SSP_8Samples; //note, this setting will only be used for DMA.. non-DMA will use a value of 1 for simplicity
gMicrowireSize = SSP_8bitCommands;
gClkdivider = 0;
gClkMode = SSP_normalmode;
gSlaveClockFreeRunning = FALSE;
gMasterSCLK = TRUE;
gMasterSFRM = FALSE;
gReceiveWithoutTransmit = TRUE;
gRxFifoOverrun = TRUE;
gAudioClockSelect = TRUE;
atomic{
gRxInProgress = FALSE;
gTxInProgress = FALSE;
}
if(gFrameFormat == SSP_PSP){
call HPLSSP.setSSPSP(SSPSP_SFRMWDTH(0)| SSPSP_SFRMDLY(0) | SSPSP_SCMODE(0));
}
SSCR1= createSSCR1();
call HPLSSP.setSSCR1(SSCR1);
SSCR0 = createSSCR0();
call HPLSSP.setSSCR0(SSCR0);
//hack for now to enable testing of this functionality
if(gAudioClockSelect == TRUE){
SSACD_1 = SSACD_ACPS(5) | SSACD_SCDB | SSACD_ACDS(1);
}
call SSPInterrupt.allocate();
call SSPInterrupt.enable();
//need to configure SSP pin for correct functionality
_PXA_setaltfn(SSP1_RXD, SSP1_RXD_ALTFN, GPIO_IN);
_PXA_setaltfn(SSP1_TXD, SSP1_TXD_ALTFN, GPIO_OUT);
//configure SCLK to run in the correct direction
if(gMasterSCLK){
_PXA_setaltfn(SSP1_SCLK, SSP1_SCLK_ALTFN, GPIO_OUT);
}
else{
_PXA_setaltfn(SSP1_SCLK, SSP1_SCLK_ALTFN, GPIO_IN);
}
//configure SFRM to run in the correct direction
if(gMasterSFRM){
_PXA_setaltfn(SSP1_SFRM, SSP1_SFRM_ALTFN, GPIO_OUT);
}
else{
_PXA_setaltfn(SSP1_SFRM, SSP1_SFRM_ALTFN, GPIO_IN);
}
return SUCCESS;
}
command result_t SSP.setSSPFormat(SSPFrameFormat_t format){
gFrameFormat = format;
return SUCCESS;
}
command result_t SSP.setDataWidth(SSPDataWidth_t width){
gDataWidth = width;
return SUCCESS;
}
command result_t SSP.enableInvertedSFRM(bool enable){
gEnableInvertedSFRM= enable;
return SUCCESS;
}
command result_t SSP.setRxFifoLevel(SSPFifoLevel_t level){
gRxFifoLevel = level;
return SUCCESS;
}
command result_t SSP.setTxFifoLevel(SSPFifoLevel_t level){
gTxFifoLevel = level;
return SUCCESS;
}
command result_t SSP.setMicrowireTxSize(SSPMicrowireTxSize_t size){
gMicrowireSize = size;
return SUCCESS;
}
//clk specific configuration routines
command result_t SSP.setClkRate(uint16_t clkdivider){
gClkdivider = clkdivider;
return SUCCESS;
}
command result_t SSP.setClkMode(SSPClkMode_t mode){
gClkMode = mode;
return SUCCESS;
}
command result_t SSP.setMasterSCLK(bool enable){
gMasterSCLK = enable;
return SUCCESS;
}
command result_t SSP.setMasterSFRM(bool enable){
gMasterSFRM = enable;
return SUCCESS;
}
command result_t SSP.setReceiveWithoutTransmit(bool enable){
gReceiveWithoutTransmit = enable;
return SUCCESS;
}
uint32_t createSSCR0(){
uint32_t temp;
//MOD:
temp = (gClkMode == SSP_normalmode)? 0 : SSCR0_MOD;
//ACS
temp |= (gAudioClockSelect == TRUE)? SSCR0_ACS : 0;
//FRDC
// temp |= FRDC(gFRDC);
//TIM (leave at the default for now)
// temp |= (gTIM == TRUE)? 0 : SSCR0_TIM;
//RIM (leave at the default for now)
temp |= (gRxFifoOverrun == TRUE)? 0 : SSCR0_RIM;
//NCS
// temp |= (gNCS == TRUE)? 0 : SSCR0_NCS;
//EDSS
temp |= (gDataWidth <= SSP_16bits)? 0 : SSCR0_EDSS;
//SCR
temp |= SSCR0_SCR(gClkdivider);
//SSE--> don't set it here in order to allow us to be a little more flexible
//temp |= SSCR0_SSE;
//ECS--> always 0 for iMote2
//FRF
temp |= SSCR0_FRF(gFrameFormat);
//DSS
temp |= SSCR0_DSS(gDataWidth);
return temp;
}
uint32_t createSSCR1(){
uint32_t temp;
//TTELP:
//temp = (gClkMode == SSP_normalmode)? 0 : SSCR0_MOD;
temp = 0;
//TTE
// temp |= (gTTE == SSP_ACS)? 0 : SSCR1_TTE;
//EBCEI
// temp |= (gEBCEI == SSP_ACS)? 0 : SSCR1_EBCEI;
//SCFR
temp |= (gSlaveClockFreeRunning == TRUE) ? 0: SSCR1_SCFR;
//ECRA
// temp |= (gECRA == TRUE)? 0 : SSCR1_ECRA;
//ECRB
// temp |= (gECRB == TRUE)? 0 : SSCR1_ECRB;
//SCLKDIR
temp |= (gMasterSCLK == TRUE)? 0: SSCR1_SCLKDIR;
//SFRMDIR
temp |= (gMasterSFRM == TRUE)? 0: SSCR1_SFRMDIR;
//RWOT
temp |= (gReceiveWithoutTransmit == TRUE)? SSCR1_RWOT : 0;
//TRAIL
// temp |= (gTRAIL == TRUE)? 0 : SSCR1_TRAIL;
//TSRE
//RSRE
//TINTE
//PINTE
// temp |= (gNCS == TRUE)? 0 : SSCR0_NCS;
//IFS
temp |= (gEnableInvertedSFRM == TRUE)? SSCR1_IFS : 0;
//STRF
//EFWR
//RFT
temp |= SSCR1_RFT(gRxFifoLevel);
//TFT
temp |= SSCR1_TFT(gTxFifoLevel);
//MWDS
temp |= (gMicrowireSize == SSP_8bitCommands)? 0 : SSCR1_MWDS;
//SPH
//SPO
//LBM
//TIE
//RIE
return temp;
}
void enableRxDMAInterrupt(){
}
void enableTxDMAInterrupt(){
}
void enableErrorInterrupts(){
}
void enableRxInterrupt(){
}
void enableTxInterrupt(){
}
command result_t BulkTxRx.BulkReceive(uint8_t *RxBuffer, uint16_t NumBytes){
//need to fake the dma transaction until we get DMA working...
gRxBuffer = RxBuffer;
gRxNumBytes = NumBytes;
gRxBufferPos = 0;
//hack for now until we get DMA fixed up...
call SingleTxRx.startReceive();
return SUCCESS;
#if 0
uint32_t temp;
if(!gRxInProgress){
if(!gTxInProgress){
//if we're neither transmitting nor receiving, setup the port how we want it be setup
uint32_t SSCR0 = createSSCR0() | SSCR0_SSE;
call HPLSSP.setSSCR1(createSSCR1());
call HPLSSP.setSSCR0(SSCR0);
//go
gRxInProgress = TRUE;
return SUCCESS;
}
}
else{
//transaction is in progress...return FAIL...(equivalent to the port being already opened)
return FAIL;
}
#endif
}
command result_t BulkTxRx.BulkTransmit(uint8_t *TxBuffer, uint16_t NumBytes){
}
command result_t SingleTxRx.startReceive(){
uint32_t SSCR0, SSCR1;
bool RxInProgress, TxInProgress;
atomic{
RxInProgress = gRxInProgress;
TxInProgress = gTxInProgress;
}
if(!RxInProgress){
if(!TxInProgress){
//if we're neither transmitting nor receiving, setup the port how we want it be setup
gNumRxFifoOverruns=0;
SSCR0 = createSSCR0() | SSCR0_SSE;
//create SSCR1 and enable the RX fifo interrupt only!!
SSCR1= createSSCR1();
call HPLSSP.setSSCR1(SSCR1 | SSCR1_RIE);
atomic gRxInProgress = TRUE;
call SSPInterrupt.enable();
//go
CKEN |= (CKEN23_SSP1);
call HPLSSP.setSSCR0(SSCR0);
if(gMasterSFRM == TRUE){
while((call HPLSSP.getSSSR()) & SSSR_CSS); //wait for the clock synchonization
}
return SUCCESS;
}
else{//tx is in progress but RX is not..just turn on the RX interrupt
SSCR1= createSSCR1();
call HPLSSP.setSSCR1(SSCR1 | SSCR1_RIE);
atomic gRxInProgress = TRUE;
return SUCCESS;
}
}
else{
//transaction is in progress...return FAIL...(equivalent to the port being already opened)
return FAIL;
}
}
command result_t SingleTxRx.stopReceive(){
uint32_t SSCR1, SSCR0;
gRxInProgress = FALSE;
if(!gTxInProgress){
//if we're neither transmitting nor receiving, kill everything
//stop the port
SSCR0 = call HPLSSP.getSSCR0();
SSCR0 &= ~SSCR0_SSE;
call HPLSSP.setSSCR0(SSCR0);
//create SSCR1 and enable the RX fifo interrupt only!!
SSCR1= call HPLSSP.getSSCR1();
SSCR1 &= ~SSCR1_RIE;
call HPLSSP.setSSCR1(SSCR1);
call SSPInterrupt.disable();
}
else{
//NOTE: SSP does not quite work in the way that we're currently representing it. Need to decide how to
//properly deal with the fact that Tx and Rx are typically coupled
//we're still transmitting....only kill the receive interrupt
SSCR1= call HPLSSP.getSSCR1();
SSCR1 &= ~SSCR1_RIE;
call HPLSSP.setSSCR1(SSCR1);
}
return SUCCESS;
}
command result_t SingleTxRx.transmit(uint32_t data){
}
task void signalSingleTxRxTransmitDone(){
//signal in a task so that we can get out of interrupt context
//signal SingleTxRx.transmitDone();
//for now, hack in a large number of samples so that we can get data out....pos
}
task void signalBulkTxRxReceiveDone(){
if(gNumRxFifoOverruns>0){
trace("Num ROR's = %d\r\n",gNumRxFifoOverruns);
}
signal BulkTxRx.BulkReceiveDone(gRxBuffer, gRxNumBytes);
}
async event void SSPInterrupt.fired(){
uint32_t temp;
//get the status register
temp = call HPLSSP.getSSSR();
if(temp & SSSR_BCE){
//bit count interrupt
call HPLSSP.setSSSR(SSSR_BCE);
}
if(temp & SSSR_TUR){
//transmit underrun
call HPLSSP.setSSSR(SSSR_TUR);
}
if(temp & SSSR_EOC){
//end of DMA Chain interrupt
call HPLSSP.setSSSR(SSSR_EOC);
}
if(temp & SSSR_TINT){
//Rx timeout interrupt
call HPLSSP.setSSSR(SSSR_TINT);
}
if(temp & SSSR_PINT){
//peripheral trailing byte interrupt
call HPLSSP.setSSSR(SSSR_PINT);
}
if(temp & SSSR_ROR){
//Rx FIFO overrrun
TOSH_CLR_YELLOW_LED_PIN();
TOSH_SET_GREEN_LED_PIN();
TOSH_SET_RED_LED_PIN();
//while(1);
gNumRxFifoOverruns++;
gRxBufferPos=0;
call HPLSSP.setSSSR(SSSR_ROR);
}
if(temp & SSSR_RFS){
atomic{
while(SSSR_1 & SSSR_RNE){
//while fifo not empty
uint32_t data = call HPLSSP.getSSDR();
((uint16_t *)gRxBuffer)[gRxBufferPos] =(uint16_t)~data;
gRxBufferPos++;
//gRxBuffer[gRxBufferPos++] = (call HPLSSP.getSSDR());
if(gRxBufferPos == gRxNumBytes){
//got all the data that we want....turn things off for now
call SingleTxRx.stopReceive();
post signalBulkTxRxReceiveDone();
}
}
} //have data to read...let's read it out!!
}
if(temp & SSSR_TFS){
post signalSingleTxRxTransmitDone();
//stupid thing wants data to send out...i.e the last set of sends are done!
}
}
}
More information about the Tinyos-beta-commits
mailing list