[Tinyos-beta-commits] CVS: tinyos-1.x/beta/platform/imote2
BTUARTC.nc, NONE, 1.1 BTUARTM.nc, NONE, 1.1 BufferedBTUARTC.nc,
NONE, 1.1 BufferedBTUARTM.nc, NONE, 1.1 BufferedFFUARTC.nc,
NONE, 1.1 BufferedFFUARTM.nc, NONE, 1.1 BufferedSTUARTC.nc,
NONE, 1.1 BufferedSTUARTM.nc, NONE, 1.1 BufferedUART.c, NONE,
1.1 BulkTxRx.h, NONE, 1.1 FFUARTC.nc, NONE, 1.1 FFUARTM.nc,
NONE, 1.1 Reset.h, NONE, 1.1 SSP.c, NONE, 1.1 SSP2C.nc, NONE,
1.1 SSP2M.nc, NONE, 1.1 STUARTC.nc, NONE, 1.1 STUARTM.nc, NONE,
1.1 SendData.nc, NONE, 1.1 SendDataAlloc.nc, NONE, 1.1 UART.c,
NONE, 1.1 sched.c, NONE, 1.1
Lama Nachman
lnachman at users.sourceforge.net
Mon Oct 9 18:18:39 PDT 2006
- Next message: [Tinyos-beta-commits] CVS: tinyos-1.x/beta/platform/imote2
BluSHC.nc, 1.4, 1.5 BluSHM.nc, 1.8, 1.9 BulkTxRx.nc, 1.2,
1.3 FlashM.nc, 1.12, 1.13 HPLCC2420M.nc, 1.8,
1.9 HPLFFUARTC.nc, 1.1, 1.2 HPLFFUARTM.nc, 1.3,
1.4 HPLSTUARTC.nc, 1.1, 1.2 HPLSTUARTM.nc, 1.3,
1.4 HPLUSBClientGPIOM.nc, 1.4, 1.5 PMIC.nc, 1.2, 1.3 PMICC.nc,
1.1, 1.2 PMICM.nc, 1.3, 1.4 SSP.nc, 1.1, 1.2 SSP1C.nc, 1.2,
1.3 SSP1M.nc, 1.4, 1.5 SettingsC.nc, 1.2, 1.3 SettingsM.nc,
1.2, 1.3 TimerJiffyAsyncC.nc, 1.1, 1.2 hardware.h, 1.8,
1.9 pmic.h, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/tinyos/tinyos-1.x/beta/platform/imote2
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv19579
Added Files:
BTUARTC.nc BTUARTM.nc BufferedBTUARTC.nc BufferedBTUARTM.nc
BufferedFFUARTC.nc BufferedFFUARTM.nc BufferedSTUARTC.nc
BufferedSTUARTM.nc BufferedUART.c BulkTxRx.h FFUARTC.nc
FFUARTM.nc Reset.h SSP.c SSP2C.nc SSP2M.nc STUARTC.nc
STUARTM.nc SendData.nc SendDataAlloc.nc UART.c sched.c
Log Message:
Pushed a new release Oct - 2006
--- NEW FILE: BTUARTC.nc ---
//@author Robbie Adler
configuration BTUARTC{
provides{
interface BulkTxRx;
//interface UART;
}
}
implementation{
components BTUARTM as UARTM,
PXA27XDMAC,
PXA27XInterruptM;
BulkTxRx=UARTM.BulkTxRx;
//UART=UARTM.UART;
UARTM.UARTInterrupt -> PXA27XInterruptM.PXA27XIrq[IID_FFUART];
UARTM.RxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
UARTM.TxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
}
--- NEW FILE: BTUARTM.nc ---
/**
* @author Robbie Adler
**/
includes mmu;
module BTUARTM {
provides {
interface BulkTxRx;
// interface UART;
}
uses {
interface PXA27XDMAChannel as RxDMAChannel;
interface PXA27XDMAChannel as TxDMAChannel;
interface PXA27XInterrupt as UARTInterrupt;
}
}
implementation {
#define _RBR BTRBR
#define _THR BTTHR
#define _DLL BTDLL
#define _IER BTIER
#define _DLH BTDLH
#define _IIR BTIIR
#define _FCR BTFCR
#define _LCR BTLCR
#define _MCR BTMCR
#define _LSR BTLSR
#define _MSR BTMSR
#define _SPR BTSPR
#define _ISR BTISR
#define _FOR BTFOR
#define _ABR BTABR
#define _ACR BTACR
#define BT_UART
//change this value to change the default priority requst for the DMA channel
#define DEFAULTDMARXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#define DEFAULTDMATXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#include "UART.c"
}
--- NEW FILE: BufferedBTUARTC.nc ---
configuration BufferedBTUARTC {
provides {
interface StdControl as Control;
interface SendData;
interface SendDataAlloc;
interface ReceiveData;
}
}
implementation {
components BufferedBTUARTM as BufferedUARTM,
BTUARTC as UARTC;
Control = BufferedUARTM;
SendData = BufferedUARTM;
SendDataAlloc = BufferedUARTM;
ReceiveData = BufferedUARTM;
BufferedUARTM.BulkTxRx -> UARTC;
}
--- NEW FILE: BufferedBTUARTM.nc ---
includes queue;
module BufferedBTUARTM {
provides {
interface StdControl;
interface SendData;
interface SendDataAlloc;
interface ReceiveData;
}
uses {
interface BulkTxRx;
}
}
implementation
{
#include "BufferedUART.c"
}
--- NEW FILE: BufferedFFUARTC.nc ---
configuration BufferedFFUARTC {
provides {
interface StdControl as Control;
interface SendData;
interface SendDataAlloc;
interface ReceiveData;
}
}
implementation {
components BufferedFFUARTM as BufferedUARTM,
FFUARTC as UARTC;
Control = BufferedUARTM;
SendData = BufferedUARTM;
SendDataAlloc = BufferedUARTM;
ReceiveData = BufferedUARTM;
BufferedUARTM.BulkTxRx -> UARTC;
}
--- NEW FILE: BufferedFFUARTM.nc ---
includes queue;
module BufferedFFUARTM {
provides {
interface StdControl;
interface SendData;
interface SendDataAlloc;
interface ReceiveData;
}
uses {
interface BulkTxRx;
}
}
implementation
{
#include "BufferedUART.c"
}
--- NEW FILE: BufferedSTUARTC.nc ---
configuration BufferedSTUARTC {
provides {
interface StdControl as Control;
interface SendData;
interface SendDataAlloc;
interface ReceiveData;
}
}
implementation {
components BufferedSTUARTM as BufferedUARTM,
STUARTC as UARTC;
Control = BufferedUARTM;
SendData = BufferedUARTM;
SendDataAlloc = BufferedUARTM;
ReceiveData = BufferedUARTM;
BufferedUARTM.BulkTxRx -> UARTC;
}
--- NEW FILE: BufferedSTUARTM.nc ---
includes queue;
module BufferedSTUARTM {
provides {
interface StdControl;
interface SendData;
interface SendDataAlloc;
interface ReceiveData;
}
uses {
interface BulkTxRx;
}
}
implementation
{
#include "BufferedUART.c"
}
--- NEW FILE: BufferedUART.c ---
#include "paramtask.h"
#define RXLINELEN 1
#define ALLOCMEM 1
#define NUMBUFFERS (10)
extern _PTR memalign(size_t, size_t) __attribute__((C,spontaneous));
#define DMA_ABLE_BUFFER(_x) ( (((uint32_t)(_x)) > 0x5c00000) && (((uint32_t)(_x)) < 0x5c040000) && ((((uint32_t)(_x))& 0x1f)== 0) )
typedef enum {
originSendData = 0,
originSendDataAlloc,
} sendOrigin_t;
typedef struct{
uint8_t *pBuf;
uint32_t numBytes;
sendOrigin_t origin;
} bufferInfo_t;
typedef struct{
char buf[RXLINELEN] __attribute ((aligned(32)));
bool inuse;
} buffer_t __attribute__((packed));
//this implementation relies on having a queue of pointers that represent the current buffer
//to be sent out
queue_t outgoingQueue;
buffer_t gRxBuffers[NUMBUFFERS];
bool gTxActive = FALSE;
void transmitDone(uint32_t arg);
DEFINE_PARAMTASK(transmitDone);
void receiveDone(uint32_t arg);
DEFINE_PARAMTASK(receiveDone);
uint8_t *getNextRxBuffer(){
int i;
uint8_t *ret = NULL;
atomic{
for(i=0;i<NUMBUFFERS; i++){
if(gRxBuffers[i].inuse == FALSE){
gRxBuffers[i].inuse = TRUE;
ret = (uint8_t *)gRxBuffers[i].buf;
break;
}
}
}
return ret;
}
void returnRxBuffer(char *buf){
int i;
atomic{
for(i=0;i<NUMBUFFERS; i++){
if(gRxBuffers[i].buf == buf){
gRxBuffers[i].inuse = FALSE;
}
}
}
}
void initRxBuffer(){
int i;
atomic{
for(i=0;i<NUMBUFFERS; i++){
gRxBuffers[i].inuse = FALSE;
}
}
}
/*
* Start of StdControl interface
*/
command result_t StdControl.init() {
initqueue(&outgoingQueue, defaultQueueSize);
gTxActive = FALSE;
return SUCCESS;
}
command result_t StdControl.start() {
uint8_t *rxBuffer = memalign(32, ((RXLINELEN+32)>>5)<<5);
call BulkTxRx.BulkReceive(rxBuffer, RXLINELEN);
return SUCCESS;
}
command result_t StdControl.stop() {
return SUCCESS;
}
/*
* End of StdControl interface
*/
/*
* Start of SendDataAlloc interface
*/
/**
* Function to allocate a buffer that is compatible with this interface.
*
* @return a non-NULL pointer to a buffer that is compatible with this interface if there is memory available to allocate. Is no memory is available, NULL will be returned
*/
command uint8_t *SendDataAlloc.alloc(size_t numBytes){
return memalign(32, ((numBytes+32)>>5)<<5);
}
command void SendDataAlloc.free(uint8_t *ptr){
if(DMA_ABLE_BUFFER(ptr)){
free(ptr);
}
else{
//debugging...this could not have been something that we allocated...
trace(DBG_USR1,"ERROR: BufferedUART.SendDataAlloc.free passed errant buffer %#x\r\n",(uint32_t)ptr);
free(ptr);
}
}
command result_t SendDataAlloc.send(uint8_t* data, uint32_t numBytes){
int ret;
bufferInfo_t *pBI;
if(!DMA_ABLE_BUFFER(data)){
trace(DBG_USR1,"ERROR: BufferedUART.SendDataAlloc.send passed nonDMAable buffer %#x\r\n",(uint32_t)data);
return FAIL;
}
pBI = malloc(sizeof(*pBI));
if(pBI == NULL){
trace(DBG_USR1,"FATAL ERROR: SendDataAlloc Unable to allocate memory for temp structure\r\n");
return FAIL;
}
pBI->pBuf = data;
pBI->numBytes = numBytes;
pBI->origin = originSendDataAlloc;
atomic{
ret = pushqueue(&outgoingQueue, (uint32_t)pBI);// see if there's enough room for this buffer
if(gTxActive == FALSE){
call BulkTxRx.BulkTransmit(pBI->pBuf, pBI->numBytes);
gTxActive = TRUE;
}
}
if(!ret){
//no room in the queue!
free(pBI);
return FAIL;
}
return SUCCESS;
}
default event result_t SendDataAlloc.sendDone(uint8_t* data, uint32_t numBytes, result_t success){
return success;
}
/*
*End of SendDataAlloc interface
*/
/*
* Start of SendData interface
*/
command result_t SendData.send(uint8_t* data, uint32_t length) {
int ret;
bufferInfo_t *pBI;
pBI = malloc(sizeof(*pBI));
if(pBI == NULL){
trace(DBG_USR1,"FATAL ERROR: SendData Unable to allocate memory for temp structure\r\n");
return FAIL;
}
#if ALLOCMEM
pBI->pBuf = memalign(32, length);
if(pBI->pBuf){
memcpy(pBI->pBuf,data,length);
}
else{
trace(DBG_USR1,"FATAL ERROR: Unable to allocate data memory\r\n");
free(pBI);
return FAIL;
}
#else
pBI->pBuf = data;
#endif
pBI->numBytes = length;
pBI->origin = originSendData;
atomic{
ret = pushqueue(&outgoingQueue, (uint32_t)pBI);// see if there's enough room for this buffer
if(gTxActive == FALSE){
call BulkTxRx.BulkTransmit(pBI->pBuf, length);
gTxActive = TRUE;
}
}
if(!ret){
//no room in the queue!
#if ALLOCMEM
free(pBI->pBuf);
#endif
free(pBI);
return FAIL;
}
return SUCCESS;
}
default event result_t SendData.sendDone(uint8_t* data, uint32_t numBytes, result_t suc) {
return suc;
}
void transmitDone(uint32_t arg){
bufferInfo_t *pBI = (bufferInfo_t *)arg;
switch(pBI->origin){
case originSendDataAlloc:
signal SendDataAlloc.sendDone(pBI->pBuf, pBI->numBytes, SUCCESS);
break;
case originSendData:
signal SendData.sendDone(pBI->pBuf, pBI->numBytes, SUCCESS);
#if ALLOCMEM
free(pBI->pBuf);
#endif
break;
default:
trace(DBG_USR1,"FATAL ERROR: BuffereUart.c found unknown interface origin %d\r\n",pBI->origin);
}
free(pBI);
atomic{
if(peekqueue(&outgoingQueue, (uint32_t *)(&pBI))){
//we still have buffers in the queue
call BulkTxRx.BulkTransmit(pBI->pBuf, pBI->numBytes);
}
else{
gTxActive = FALSE;
}
}
}
void receiveDone(uint32_t arg){
bufferInfo_t *pBI = (bufferInfo_t *)arg;
if(pBI == NULL){
return;
}
signal ReceiveData.receive(pBI->pBuf, pBI->numBytes);
returnRxBuffer(pBI->pBuf);
free(pBI);
}
/*
* Start of ReceiveData interface
*/
default event result_t ReceiveData.receive(uint8_t* Data, uint32_t Length) {
return SUCCESS;
}
/*
* End of ReceiveData interface
*/
/*
* End of SendData interface
*/
async event uint8_t *BulkTxRx.BulkReceiveDone(uint8_t *RxBuffer,
uint16_t NumBytes){
bufferInfo_t *pBI;
uint8_t *newBuffer;
pBI = malloc(sizeof(*pBI));
if(pBI == NULL){
trace(DBG_USR1,"FATAL ERROR: Unable to allocate memory for temp structure\r\n");
return NULL;
}
pBI->pBuf = RxBuffer;
pBI->numBytes = NumBytes;
POST_PARAMTASK(receiveDone,pBI);
newBuffer = getNextRxBuffer();
if(newBuffer == NULL){
trace(DBG_USR1,"FATAL ERROR: Unable to allocate memory for receiveBuffer\r\n");
}
return newBuffer;
}
async event BulkTxRxBuffer_t *BulkTxRx.BulkTxRxDone(BulkTxRxBuffer_t *TxRxBuffer, uint16_t NumBytes){
return NULL;
}
async event uint8_t *BulkTxRx.BulkTransmitDone(uint8_t *TxBuffer, uint16_t NumBytes){
bufferInfo_t *pBI;
if(popqueue(&outgoingQueue, (uint32_t *)(&pBI))){
//got a buffer out of the queue...make sure that it's the same as what we just got back
if((pBI->pBuf == TxBuffer) && (pBI->numBytes == NumBytes)){
//got the right buffer back!!
POST_PARAMTASK(transmitDone,pBI);
}
else{
trace(DBG_USR1,"FATAL ERROR: found unexpected buffer in queue\r\n");
}
}
else{
trace(DBG_USR1,"FATAL ERROR: unexpected tranmit queue empty during\r\n");
}
return NULL;
}
--- NEW FILE: BulkTxRx.h ---
#ifndef __BULK_TX_RX_H__
#define __BULK_TX_RX_H__
typedef struct{
uint8_t *RxBuffer;
uint8_t *TxBuffer;
} BulkTxRxBuffer_t;
#endif //__BULK_TX_RX_H__
--- NEW FILE: FFUARTC.nc ---
//@author Robbie Adler
configuration FFUARTC{
provides{
interface BulkTxRx;
//interface UART;
}
}
implementation{
components FFUARTM as UARTM,
PXA27XDMAC,
PXA27XInterruptM;
BulkTxRx=UARTM.BulkTxRx;
//UART=UARTM.UART;
UARTM.UARTInterrupt -> PXA27XInterruptM.PXA27XIrq[IID_FFUART];
UARTM.RxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
UARTM.TxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
}
--- NEW FILE: FFUARTM.nc ---
/**
* @author Robbie Adler
**/
includes mmu;
module FFUARTM {
provides {
interface BulkTxRx;
// interface UART;
}
uses {
interface PXA27XDMAChannel as RxDMAChannel;
interface PXA27XDMAChannel as TxDMAChannel;
interface PXA27XInterrupt as UARTInterrupt;
}
}
implementation {
#define _RBR FFRBR
#define _THR FFTHR
#define _DLL FFDLL
#define _IER FFIER
#define _DLH FFDLH
#define _IIR FFIIR
#define _FCR FFFCR
#define _LCR FFLCR
#define _MCR FFMCR
#define _LSR FFLSR
#define _MSR FFMSR
#define _SPR FFSPR
#define _ISR FFISR
#define _FOR FFFOR
#define _ABR FFABR
#define _ACR FFACR
#define FF_UART
//change this value to change the default priority requst for the DMA channel
#define DEFAULTDMARXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#define DEFAULTDMATXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#include "UART.c"
}
--- NEW FILE: Reset.h ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
*
* Authors: Lama Nachman
*
*/
#ifndef RESET_H
#define RESET_H
#define GPIO_RESET 0x8
#define SLEEP_RESET 0x4
#define WDT_RESET 0x2
#define HW_RESET 0x1
#endif
--- NEW FILE: SSP.c ---
/**
* @author Robbie Adler
**/
/***
*
* standard implentation for all iMote2 SSP modules. This file is in
* intended to #included into the respectived SSPXM.nc module
*
**/
//declare component state and initialize it to something reasonable just in case the user does something stupid
SSPFrameFormat_t gFrameFormat = SSP_SSP;
SSPDataWidth_t gDataWidth = SSP_16bits;
bool gEnableInvertedSFRM = TRUE;
SSPFifoLevel_t gRxFifoLevel = SSP_8Samples;
SSPFifoLevel_t gTxFifoLevel = SSP_8Samples;
SSPMicrowireTxSize_t gMicrowireSize = SSP_8bitCommands;
uint16_t gClkdivider = 1;
SSPClkMode_t gClkMode = SSP_normalmode;
bool gSlaveClockFreeRunning = FALSE;
bool gMasterSCLK = TRUE;
bool gMasterSFRM = TRUE;
bool gReceiveWithoutTransmit = FALSE;
bool gRxFifoOverrun = TRUE;
bool gAudioClockSelect = FALSE;
bool gEnableSPIClkHigh = FALSE;
bool gShiftSPIClk = FALSE;
bool gPortInUse = FALSE;
bool gPortInitialized = FALSE;
bool gManualRxPinCtrl = FALSE;
bool gManualTxPinCtrl = FALSE;
bool gManualSFRMPinCtrl = FALSE;
bool gManualSCLKPinCtrl = FALSE;
//NOTE: ARM HW guarantees that interrupts are disabled upon entering the handler. This will be true
// so long as we don't enable nested interrupts.
norace bool gFullDuplex = FALSE;
norace bool gHalfDuplex_Tx = FALSE;
norace bool gDMARxDone = FALSE;
norace bool gDMATxDone = FALSE;
bool gDMARxReady = FALSE;
bool gDMATxReady = FALSE;
uint8_t DummyReceive[32] __attribute__((aligned(32)));
norace uint16_t gNumRxFifoOverruns;
//norace hack!!!
norace uint16_t *gRxBuffer;
norace uint16_t gRxNumBytes, gRxBufferPos;
//norace hack!!!
norace uint16_t *gTxBuffer;
norace uint16_t gTxNumBytes, gTxBufferPos;
//norace hack!!!
norace BulkTxRxBuffer_t *gTxRxBuffer;
norace uint16_t gTxRxNumBytes;
uint32_t createSSCR0();
uint32_t createSSCR1();
result_t tryFullDuplex();
result_t TxRxInterruptHelper() __attribute__((always_inline));
result_t openPort(bool bRxDMAIntEnable, bool bTxDMAIntEnable){
result_t status=SUCCESS;
atomic{
if(gPortInUse==TRUE){
status = FAIL;
}
else{
gPortInUse = TRUE;
}
}
if(status==FAIL){
return FAIL;
}
//turn on the port's clock
CKEN |= (MYCKEN);
if(gFrameFormat == SSP_PSP){
_SSPSP = (SSPSP_SFRMWDTH(0)| SSPSP_SFRMDLY(0) | SSPSP_SCMODE(0));
}
_SSCR1= createSSCR1() | SSCR1_TRAIL | ((bRxDMAIntEnable==TRUE)?SSCR1_RSRE:0) | ((bTxDMAIntEnable==TRUE)?SSCR1_TSRE:0);
_SSCR0 = createSSCR0();
//clear the timeout bit in case it is already set (since we might not be handling that interrupts)
_SSSR = SSSR_TINT;
_SSTO = 512;
//hack for now to enable testing of this fuunctionality
if(gAudioClockSelect == TRUE){
_SSACD = SSACD_ACPS(5) | SSACD_SCDB | SSACD_ACDS(1);
}
//initialize the port's interrupts and DMA channels if
//it hasn't happened yet.
if(gPortInitialized==FALSE){
call SSPInterrupt.allocate();
call SSPInterrupt.enable();
gPortInitialized = TRUE;
}
//need to configure SSP pin for correct functionality
if(gManualRxPinCtrl == FALSE){
GPIO_SET_ALT_FUNC(MYSSP_RXD, MYSSP_RXD_ALTFN, GPIO_IN);
}
if(gManualTxPinCtrl == FALSE){
GPIO_SET_ALT_FUNC(MYSSP_TXD, MYSSP_TXD_ALTFN, GPIO_OUT);
}
//configure SCLK to run in the correct direction
if(gManualSCLKPinCtrl == FALSE){
if(gMasterSCLK){
GPIO_SET_ALT_FUNC(MYSSP_SCLK, MYSSP_SCLK_ALTFN, GPIO_OUT);
}
else{
GPIO_SET_ALT_FUNC(MYSSP_SCLK, MYSSP_SCLK_ALTFN, GPIO_IN);
}
}
//configure SFRM to run in the correct direction
if(gManualSFRMPinCtrl == FALSE){
if(gMasterSFRM){
GPIO_SET_ALT_FUNC(MYSSP_SFRM, MYSSP_SFRM_ALTFN, GPIO_OUT);
}
else{
GPIO_SET_ALT_FUNC(MYSSP_SFRM, MYSSP_SFRM_ALTFN, GPIO_IN);
}
}
return SUCCESS;
}
result_t closePort(){
atomic {
gPortInUse = FALSE;
gFullDuplex = FALSE;
gHalfDuplex_Tx = FALSE;
gDMARxReady = FALSE;
gDMATxReady = FALSE;
gDMARxDone = FALSE;
gDMATxDone = FALSE;
gRxBuffer = NULL;
gRxNumBytes = 0;
gTxBuffer = NULL;
gTxNumBytes = 0;
gTxRxBuffer= NULL;
gTxRxNumBytes = 0;
}
_SSCR0 &= ~SSCR0_SSE;
//turn off the port's clock
CKEN &= ~(MYCKEN);
return SUCCESS;
}
void configureRxDMA(uint8_t *RxBuffer, uint16_t NumBytes, bool bEnableTargetAddrIncrement){
call RxDMAChannel.setSourceAddr(MYFIFOADDR);
call RxDMAChannel.setTargetAddr((uint32_t)RxBuffer);
call RxDMAChannel.enableSourceAddrIncrement(FALSE);
call RxDMAChannel.enableTargetAddrIncrement(bEnableTargetAddrIncrement);
call RxDMAChannel.enableSourceFlowControl(TRUE);
call RxDMAChannel.enableTargetFlowControl(FALSE);
call RxDMAChannel.setTransferLength(NumBytes);
//need to fix to guarantee that this is generic
call RxDMAChannel.setMaxBurstSize( ((gRxFifoLevel+1) * (gDataWidth + 1)>>3)>>4);
call RxDMAChannel.setTransferWidth((gDataWidth+1)>>3);
}
//default events....Note that the default events are an all or nothing thing. If you
//implement one of the handlers, you have to implement all of them
default async event uint8_t *BulkTxRx.BulkReceiveDone(uint8_t *RxBuffer,
uint16_t NumBytes){return NULL;}
default async event uint8_t *BulkTxRx.BulkTransmitDone(uint8_t *TxBuffer,
uint16_t NumBytes){return NULL;}
default async event BulkTxRxBuffer_t *BulkTxRx.BulkTxRxDone(BulkTxRxBuffer_t *TxRxBuffer,
uint16_t NumBytes){return NULL;}
command result_t BulkTxRx.BulkReceive(uint8_t *RxBuffer, uint16_t NumBytes){
//call SSPInterrupt.disable();
if(openPort(TRUE, FALSE)==FAIL){
return FAIL;
}
atomic{
gRxBuffer = (uint16_t *)RxBuffer;
gRxNumBytes = NumBytes;
gRxBufferPos = 0;
gNumRxFifoOverruns=0;
gFullDuplex = FALSE;
gHalfDuplex_Tx = FALSE;
}
configureRxDMA(RxBuffer, NumBytes, TRUE);
//request a non-permanent channel
call RxDMAChannel.requestChannel(DMAID_MYSSP_RX,DEFAULTDMARXPRIORITY, FALSE);
return SUCCESS;
}
event result_t RxDMAChannel.requestChannelDone(){
//so we've successfully been cleared to start doing something with our port...go!!
uint32_t SSCR0;
bool localFullDuplex, localHalfDuplex_Tx;
atomic{
localFullDuplex = gFullDuplex;
localHalfDuplex_Tx = gHalfDuplex_Tx;
}
if(localFullDuplex==TRUE || localHalfDuplex_Tx==TRUE){
atomic{
gDMARxReady = TRUE;
}
tryFullDuplex();
}
else{
call RxDMAChannel.run(TRUE);
SSCR0 = _SSCR0 | SSCR0_SSE;
_SSCR0 = SSCR0;
}
return SUCCESS;
}
async event void RxDMAChannel.Interrupt(){
//invlidate the DCache so that we can bring our data in
gDMARxDone=TRUE;
if(TxRxInterruptHelper() == FAIL && gFullDuplex == FALSE && gHalfDuplex_Tx == FALSE){
//we got here because we're in RWOT mode
invalidateDCache((uint8_t *)gRxBuffer, gRxNumBytes);
gRxBuffer = (uint16_t *)signal BulkTxRx.BulkReceiveDone((uint8_t *)gRxBuffer,
gRxNumBytes);
if(gRxBuffer){
//we want to do another read of gRxNumBytes)
//we should still have our DMA channel, so just all set size and run!
call RxDMAChannel.setTargetAddr((uint32_t)gRxBuffer);
call RxDMAChannel.setTransferLength(gRxNumBytes);
call RxDMAChannel.run(TRUE);
}
else{
if(gNumRxFifoOverruns>0){
trace(DBG_USR1,"Num ROR's = %d\r\n",gNumRxFifoOverruns);
}
closePort();
}
}
return;
}
void configureTxDMA(uint8_t *TxBuffer, uint16_t NumBytes){
call TxDMAChannel.setSourceAddr((uint32_t)TxBuffer);
call TxDMAChannel.setTargetAddr(MYFIFOADDR);
call TxDMAChannel.enableSourceAddrIncrement(TRUE);
call TxDMAChannel.enableTargetAddrIncrement(FALSE);
call TxDMAChannel.enableSourceFlowControl(FALSE);
call TxDMAChannel.enableTargetFlowControl(TRUE);
call TxDMAChannel.setTransferLength(NumBytes);
//need to fix to guarantee that this is generic
call TxDMAChannel.setMaxBurstSize( ((gTxFifoLevel+1) * (gDataWidth + 1)>>3)>>4);
call TxDMAChannel.setTransferWidth((gDataWidth+1)>>3);
}
command result_t BulkTxRx.BulkTransmit(uint8_t *TxBuffer, uint16_t NumBytes){
if(gReceiveWithoutTransmit==TRUE){
//the user want to configure the port to be in receive without transmit mode...this won't work well
return FAIL;
}
if(openPort(TRUE, TRUE)==FAIL){
//port was already open
return FAIL;
}
//port has now been opened
atomic{
gTxBuffer = (uint16_t *)TxBuffer;
gTxNumBytes = NumBytes;
gFullDuplex = FALSE;
gHalfDuplex_Tx = TRUE;
gDMARxDone = FALSE;
gDMATxDone = FALSE;
gDMARxReady = FALSE;
gDMATxReady = FALSE;
}
//flush the data back to memory
cleanDCache(TxBuffer, NumBytes);
configureTxDMA(TxBuffer,NumBytes);
configureRxDMA(DummyReceive,NumBytes, FALSE);
//request a non-permanent channel
call TxDMAChannel.requestChannel(DMAID_MYSSP_TX,DEFAULTDMATXPRIORITY, FALSE);
call RxDMAChannel.requestChannel(DMAID_MYSSP_RX,DEFAULTDMARXPRIORITY, FALSE);
return SUCCESS;
}
event result_t TxDMAChannel.requestChannelDone(){
//so we've successfully been cleared to start doing something with our port...go!!
atomic{
gDMATxReady = TRUE;
}
tryFullDuplex();
return SUCCESS;
}
async event void TxDMAChannel.Interrupt(){
gDMATxDone=TRUE;
if(TxRxInterruptHelper() == FAIL){
if(gFullDuplex == FALSE && gHalfDuplex_Tx == FALSE){
//catastrophic error...not sure why we have this interrupt
closePort();
}
}
return;
}
result_t TxRxInterruptHelper() __attribute__((always_inline)){
if(gDMATxDone==TRUE && gDMARxDone==TRUE){
if(gFullDuplex == TRUE){
invalidateDCache((uint8_t *)gTxRxBuffer->RxBuffer, gTxRxNumBytes);
gTxRxBuffer = signal BulkTxRx.BulkTxRxDone(gTxRxBuffer,gTxRxNumBytes);
if(gTxRxBuffer && gTxRxBuffer->RxBuffer && gTxRxBuffer->TxBuffer){
cleanDCache(gTxRxBuffer->TxBuffer, gTxRxNumBytes);
gDMARxDone=FALSE;
gDMATxDone=FALSE;
call RxDMAChannel.setTargetAddr((uint32_t)gTxRxBuffer->RxBuffer);
call RxDMAChannel.setTransferLength(gTxRxNumBytes);
call RxDMAChannel.run(TRUE);
call TxDMAChannel.setSourceAddr((uint32_t)gTxRxBuffer->TxBuffer);
call TxDMAChannel.setTransferLength(gTxRxNumBytes);
call TxDMAChannel.run(TRUE);
}
else{
closePort();
}
return SUCCESS;
}
else if(gHalfDuplex_Tx == TRUE){
gTxBuffer = (uint16_t *)signal BulkTxRx.BulkTransmitDone((uint8_t *)gTxBuffer,
gTxNumBytes);
if(gTxBuffer){
//we want to do another writeof gTxNumBytes)
//we should still have our DMA channel, so just all set size and run!
cleanDCache((uint8_t *)gTxBuffer, gTxNumBytes);
gDMARxDone=FALSE;
gDMATxDone=FALSE;
call RxDMAChannel.setTransferLength(gTxNumBytes);
call RxDMAChannel.run(TRUE);
call TxDMAChannel.setSourceAddr((uint32_t)gTxBuffer);
call TxDMAChannel.setTransferLength(gTxNumBytes);
call TxDMAChannel.run(TRUE);
}
else{
closePort();
}
return SUCCESS;
}
}
return FAIL;
}
command result_t BulkTxRx.BulkTxRx(BulkTxRxBuffer_t *TxRxBuffer, uint16_t NumBytes){
if(gReceiveWithoutTransmit==TRUE){
//the user want to configure the port to be in receive without transmit mode...this won't work well
return FAIL;
}
if(openPort(TRUE, TRUE)==FAIL){
//port was already open
return FAIL;
}
//port has now been opened
atomic{
gTxRxBuffer = TxRxBuffer;
gTxRxNumBytes = NumBytes;
gFullDuplex = TRUE;
gHalfDuplex_Tx = FALSE;
gDMARxDone = FALSE;
gDMATxDone = FALSE;
gDMARxReady = FALSE;
gDMATxReady = FALSE;
}
//flush the buffer back to memory
cleanDCache(TxRxBuffer->TxBuffer, NumBytes);
configureRxDMA(TxRxBuffer->RxBuffer, NumBytes, TRUE);
configureTxDMA(TxRxBuffer->TxBuffer, NumBytes);
//request 2 non-permanent channels
call RxDMAChannel.requestChannel(DMAID_MYSSP_RX,DEFAULTDMARXPRIORITY, FALSE);
call TxDMAChannel.requestChannel(DMAID_MYSSP_TX,DEFAULTDMATXPRIORITY, FALSE);
return SUCCESS;
}
result_t tryFullDuplex(){
bool local_TxReady, local_RxReady;
atomic{
local_TxReady = gDMATxReady;
local_RxReady = gDMARxReady;
}
if(local_TxReady == TRUE && local_RxReady == TRUE){
uint32_t SSCR0;
call TxDMAChannel.run(TRUE);
call RxDMAChannel.run(TRUE);
SSCR0 = _SSCR0 | SSCR0_SSE;
_SSCR0 = SSCR0;
return SUCCESS;
}
return FAIL;
}
async event void SSPInterrupt.fired(){
uint32_t SSSR;
uint32_t SSCR1;
uint32_t SSCR0;
//get the status register
SSSR = _SSSR;
SSCR1 = _SSCR1;
SSCR0 = _SSCR0;
if((SSSR & SSSR_BCE) && (SSCR1 & SSCR1_EBCEI) ){
//bit count interrupt
_SSSR = SSSR_BCE;
}
if((SSSR & SSSR_TUR) && (SSCR0 & SSCR0_TIM)){
//transmit underrun
_SSSR = SSSR_TUR;
}
if(SSSR & SSSR_EOC){
//end of DMA Chain interrupt
_SSSR = SSSR_EOC;
}
if((SSSR & SSSR_TINT) && (SSCR1 & SSCR1_TINTE)){
//Rx timeout interrupt
_SSSR = SSSR_TINT;
}
if((SSSR & SSSR_PINT) && (SSCR1 & SSCR1_PINTE)){
//peripheral trailing byte interrupt
_SSSR = SSSR_PINT;
}
if((SSSR & SSSR_ROR) && (SSCR0 & SSCR0_RIM)){
//Rx FIFO overrrun
//while(1);
gNumRxFifoOverruns++;
//gRxBufferPos=0;
_SSSR = SSSR_ROR;
}
if((SSSR & SSSR_RFS) && (SSCR1 & SSCR1_RIE)){
//atomic
//uint16_t data;
{
while(SSSR_1 & SSSR_RNE){
//while fifo not empty
//data = SSDR_1;
//*gRxBuffer++ =(uint16_t)~data;
if(gRxBuffer){
*gRxBuffer++ = SSDR_1;
gRxBufferPos++;
}
//gRxBuffer[gRxBufferPos++] = _SSDR
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((SSSR & SSSR_TFS) && (SSCR1 & SSCR1_TIE)){
//post signalSingleTxRxTransmitDone();
//stupid thing wants data to send out...i.e the last set of sends are done!
}
}
/**
*SSP Port configuration commands
**/
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.enableSPIClkHigh(bool enable){
gEnableSPIClkHigh = enable;
return SUCCESS;
}
command result_t SSP.shiftSPIClk(bool enable){
gShiftSPIClk = 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.enableManualRxPinCtrl(bool enable){
gManualRxPinCtrl = enable;
return SUCCESS;
}
command result_t SSP.enableManualTxPinCtrl(bool enable){
gManualTxPinCtrl = enable;
return SUCCESS;
}
command result_t SSP.enableManualSFRMPinCtrl(bool enable){
gManualSFRMPinCtrl = enable;
return SUCCESS;
}
command result_t SSP.enableManualSCLKPinCtrl(bool enable){
gManualSCLKPinCtrl = enable;
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
temp |= (gShiftSPIClk == TRUE) ? SSCR1_SPH : 0;
temp |= (gEnableSPIClkHigh == TRUE) ? SSCR1_SPO : 0;
//LBM
//TIE
//RIE
return temp;
}
--- NEW FILE: SSP2C.nc ---
//@author Robbie Adler
configuration SSP2C{
provides{
interface BulkTxRx;
interface SSP;
}
}
implementation{
components SSP2M as SSPM,
PXA27XDMAC,
PXA27XInterruptM;
BulkTxRx=SSPM.BulkTxRx;
SSP=SSPM.SSP;
SSPM.SSPInterrupt -> PXA27XInterruptM.PXA27XIrq[IID_SSP2];
SSPM.RxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
SSPM.TxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
}
--- NEW FILE: SSP2M.nc ---
/**
* @author Robbie Adler
**/
includes mmu;
module SSP2M {
provides {
interface BulkTxRx;
interface SSP;
}
uses {
interface PXA27XDMAChannel as RxDMAChannel;
interface PXA27XDMAChannel as TxDMAChannel;
interface PXA27XInterrupt as SSPInterrupt;
}
}
implementation {
#define _SSCR0 SSCR0_2
#define _SSCR1 SSCR1_2
#define _SSPSP SSPSP_2
#define _SSTO SSTO_2
#define _SSITR SSITR_2
#define _SSSR SSSR_2
#define _SSDR SSDR_2
#define _SSACD SSACD_2
#define MYCKEN (CKEN_CKEN3)
#define MYFIFOADDR (0x41700010)
#define MYSSP_RXD SSP2_RXD
#define MYSSP_RXD_ALTFN SSP2_RXD_ALTFN
#define MYSSP_TXD SSP2_TXD
#define MYSSP_TXD_ALTFN SSP2_TXD_ALTFN
#define MYSSP_SCLK SSP2_SCLK
#define MYSSP_SCLK_ALTFN SSP2_SCLK_ALTFN
#define MYSSP_SFRM SSP2_SFRM
#define MYSSP_SFRM_ALTFN SSP2_SFRM_ALTFN
#define DMAID_MYSSP_TX DMAID_SSP2_TX
#define DMAID_MYSSP_RX DMAID_SSP2_RX
//change this value to change the default priority requst for the DMA channel
#define DEFAULTDMARXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#define DEFAULTDMATXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#include "SSP.c"
}
--- NEW FILE: STUARTC.nc ---
//@author Robbie Adler
configuration STUARTC{
provides{
interface BulkTxRx;
//interface UARTConfig;
}
}
implementation{
components STUARTM as UARTM,
PXA27XDMAC,
PXA27XInterruptM;
BulkTxRx=UARTM.BulkTxRx;
//UART=UARTM.UART;
UARTM.UARTInterrupt -> PXA27XInterruptM.PXA27XIrq[IID_FFUART];
UARTM.RxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
UARTM.TxDMAChannel -> PXA27XDMAC.PXA27XDMAChannel[unique("DMAChannel")];
}
--- NEW FILE: STUARTM.nc ---
/**
* @author Robbie Adler
**/
includes mmu;
module STUARTM {
provides {
interface BulkTxRx;
// interface UART;
}
uses {
interface PXA27XDMAChannel as RxDMAChannel;
interface PXA27XDMAChannel as TxDMAChannel;
interface StdControl as DMAControl;
interface PXA27XInterrupt as UARTInterrupt;
}
}
implementation {
#define _RBR STRBR
#define _THR STTHR
#define _DLL STDLL
#define _IER STIER
#define _DLH STDLH
#define _IIR STIIR
#define _FCR STFCR
#define _LCR STLCR
#define _MCR STMCR
#define _LSR STLSR
#define _MSR STMSR
#define _SPR STSPR
#define _ISR STISR
#define _FOR STFOR
#define _ABR STABR
#define _ACR STACR
#define ST_UART
//change this value to change the default priority requst for the DMA channel
#define DEFAULTDMARXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#define DEFAULTDMATXPRIORITY (DMA_Priority1|DMA_Priority2|DMA_Priority3|DMA_Priority4)
#include "UART.c"
}
--- NEW FILE: SendData.nc ---
// $Id: SendData.nc,v 1.1 2006/10/10 01:18:37 lnachman Exp $
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
* Authors: Jason Hill, David Gay, Philip Levis
* Date last modified: 6/25/02
*
*
*/
/**
* Interface for sending arbitrary streams of bytes.
*
* @author Jason Hill
* @author David Gay
* @author Philip Levis
*/
interface SendData
{
/**
* Send <code>numBytes</code> of the buffer <code>data</code>.
*
* @return SUCCESS if send request accepted, FAIL otherwise. SUCCCES
* means that a sendDone should be expected, FAIL means it should
* not.
*/
command result_t send(uint8_t* packet, uint32_t numBytes);
/**
* Send request completed. The buffer sent and whether the send was
* successful are passed.
*
* @return SUCCESS always.
*/
event result_t sendDone(uint8_t* packet, uint32_t numBytes, result_t success);
}
--- NEW FILE: SendDataAlloc.nc ---
/*
* Authors: Robbie Adler
* Date last modified: 8/25/06
* based on SendData.nc written by Jason Hill, David Gay, Philip Levis
*
*
*/
/**
* Interface for sending arbitrary streams of bytes based on a buffer that allocated by the module itself.
*
* @author Robbie Adler
*/
interface SendDataAlloc
{
/**
* Function to allocate a buffer that is compatible with this interface.
*
* @return a non-NULL pointer to a buffer that is compatible with this interface if there is memory available to allocate. Is no memory is available, NULL will be returned
*/
command uint8_t *alloc(size_t numBytes);
/**
* Function to free a buffer that was allocated by this function's alloc interface
*
* @return void
*/
command void free(uint8_t *ptr);
/**
* Send <code>numBytes</code> of the buffer <code>data</code>.
*
* @return SUCCESS if send request accepted, FAIL otherwise. SUCCCES
* means that a sendDone should be expected, FAIL means it should
* not. This command assumes that the pointer passed in via the packet parameter was allocated using the interface's alloc function
*/
command result_t send(uint8_t* packet, uint32_t numBytes);
/**
* Send request completed. The buffer sent and whether the send was
* successful are passed.
*
* @return SUCCESS always.
*/
event result_t sendDone(uint8_t* packet, uint32_t numBytes, result_t success);
}
--- NEW FILE: UART.c ---
/**
* @author Robbie Adler
**/
/***
*
* standard implentation for all iMote2 UART modules. This file is in
* intended to be #included into the respectived XUARTM.nc module
*
**/
#ifdef ST_UART
#define MYFIFOADDR 0x40700000
#define MYCKEN (CKEN_CKEN5)
#define DMAID_MYUART_TX DMAID_STUART_TX
#define DMAID_MYUART_RX DMAID_STUART_RX
#endif
#ifdef BT_UART
#define MYFIFOADDR 0x40200000
#define MYCKEN (CKEN_CKEN7)
#define DMAID_MYUART_TX DMAID_BTUART_TX
#define DMAID_MYUART_RX DMAID_BTUART_RX
#endif
#ifdef FF_UART
#define MYFIFOADDR 0x40100000
#define MYCKEN (CKEN_CKEN6)
#define DMAID_MYUART_TX DMAID_FFUART_TX
#define DMAID_MYUART_RX DMAID_FFUART_RX
#endif
//declare component state and initialize it to something reasonable just in case the user does something stupid
norace bool gTxPortInUse = FALSE;
norace bool gRxPortInUse = FALSE;
bool gPortInitialized = FALSE;
norace uint16_t gNumRxFifoOverruns;
norace uint8_t *gRxBuffer;
norace uint16_t gRxNumBytes;
norace uint8_t *gTxBuffer;
norace uint16_t gTxNumBytes, gTxBufferPos;
void initPort(){
//configure the GPIO Alt functions and directions
#ifdef ST_UART
GPIO_SET_ALT_FUNC(46,2,GPIO_IN);
GPIO_SET_ALT_FUNC(47,1,GPIO_OUT);
#endif
#ifdef BT_UART
#endif
#ifdef FF_UART
GPIO_SET_ALT_FUNC(96,3, GPIO_IN);
GPIO_SET_ALT_FUNC(99,3, GPIO_OUT); //FFTXD
#endif
call UARTInterrupt.allocate();
// call UARTInterrupt.enable();
}
void configPort(){
//turn on the port's clock
CKEN |= (MYCKEN);
_IER = IER_DMAE;
_IER |= IER_UUE; //enable the UART
_LCR |=LCR_DLAB; //turn on DLAB so we can change the divisor
_DLL = 8; //configure to 115200;
_DLH = 0;
_LCR &= ~(LCR_DLAB); //turn off DLAB
_LCR |= 0x3; //configure to 8 bits
//STMCR |= MCR_AFE; //Auto flow control enabled;
//STMCR |= MCR_RTS;
_FCR = 0xFF;// FCR_ITL(2) | FCR_BUS | FCR_TRAIL | FCR_TIL | FCR_RESETTF | FCR_TRFIFOE;
_MCR &= ~MCR_LOOP;
_MCR |= MCR_OUT2;
//_IER |= IER_RAVIE;
//_IER |= IER_TIE;
}
result_t openTxPort(bool bTxDMAIntEnable){
result_t status=SUCCESS;
atomic{
if(gTxPortInUse==TRUE){
status = FAIL;
}
else{
gTxPortInUse = TRUE;
}
}
if(status==FAIL){
return FAIL;
}
if(gPortInitialized==FALSE){
initPort();
gPortInitialized = TRUE;
}
atomic{
if(gRxPortInUse == FALSE){
//other side does not have the port open
configPort();
}
}
return SUCCESS;
}
result_t openRxPort(bool bRxDMAIntEnable){
result_t status=SUCCESS;
atomic{
if(gRxPortInUse==TRUE){
status = FAIL;
}
else{
gRxPortInUse = TRUE;
}
}
if(status==FAIL){
return FAIL;
}
if(gPortInitialized==FALSE){
initPort();
gPortInitialized = TRUE;
}
atomic{
if(gTxPortInUse == FALSE){
//other side does not have the port open
configPort();
}
}
return SUCCESS;
}
result_t closeTxPort(){
//this function will only be called from interrupt context
//ARM guarantees that our interrupt will be disabled
gTxPortInUse = FALSE;
gTxBuffer = NULL;
gTxNumBytes = 0;
//wait until we've shifted out all of our data
while(!(_LSR & LSR_TEMT));
if(gRxPortInUse == FALSE){
//turn off the port's clock
_IER &= ~IER_UUE; //enable the UART
CKEN &= ~(MYCKEN);
}
return SUCCESS;
}
result_t closeRxPort(){
//this function will only be called from interrupt context
//ARM guarantees that our interrupt will be disabled
gRxPortInUse = FALSE;
gRxBuffer = NULL;
gRxNumBytes = 0;
if(gTxPortInUse == FALSE){
//turn off the port's clock
_IER &= ~IER_UUE; //enable the UART
CKEN &= ~(MYCKEN);
}
return SUCCESS;
}
void configureRxDMA(uint8_t *RxBuffer, uint16_t NumBytes, bool bEnableTargetAddrIncrement){
call RxDMAChannel.setSourceAddr(MYFIFOADDR);
call RxDMAChannel.setTargetAddr((uint32_t)RxBuffer);
call RxDMAChannel.enableSourceAddrIncrement(FALSE);
call RxDMAChannel.enableTargetAddrIncrement(bEnableTargetAddrIncrement);
call RxDMAChannel.enableSourceFlowControl(TRUE);
call RxDMAChannel.enableTargetFlowControl(FALSE);
call RxDMAChannel.setTransferLength(NumBytes);
//need to fix to guarantee that this is generic
call RxDMAChannel.setMaxBurstSize(DMA_32ByteBurst);
call RxDMAChannel.setTransferWidth(DMA_1ByteWidth);
}
//default events....Note that the default events are an all or nothing thing. If you
//implement one of the handlers, you have to implement all of them
default async event uint8_t *BulkTxRx.BulkReceiveDone(uint8_t *RxBuffer,
uint16_t NumBytes){return NULL;}
default async event uint8_t *BulkTxRx.BulkTransmitDone(uint8_t *TxBuffer,
uint16_t NumBytes){return NULL;}
default async event BulkTxRxBuffer_t *BulkTxRx.BulkTxRxDone(BulkTxRxBuffer_t *TxRxBuffer,
uint16_t NumBytes){return NULL;}
command result_t BulkTxRx.BulkReceive(uint8_t *RxBuffer, uint16_t NumBytes){
call UARTInterrupt.disable();
if(openRxPort(TRUE)==FAIL){
return FAIL;
}
atomic{
gRxBuffer = RxBuffer;
gRxNumBytes = NumBytes;
gNumRxFifoOverruns=0;
}
configureRxDMA(RxBuffer, NumBytes, TRUE);
//request a non-permanent channel
call RxDMAChannel.requestChannel(DMAID_MYUART_RX,DEFAULTDMARXPRIORITY, FALSE);
return SUCCESS;
}
event result_t RxDMAChannel.requestChannelDone(){
//so we've successfully been cleared to start doing something with our port...go!!
call RxDMAChannel.run(TRUE);
return SUCCESS;
}
async event void RxDMAChannel.Interrupt(){
//invlidate the DCache so that we can bring our data in
invalidateDCache(gRxBuffer, gRxNumBytes);
gRxBuffer = signal BulkTxRx.BulkReceiveDone(gRxBuffer,
gRxNumBytes);
if(gRxBuffer){
//we want to do another read of gRxNumBytes)
//we should still have our DMA channel, so just all set size and run!
call RxDMAChannel.setTargetAddr((uint32_t)gRxBuffer);
call RxDMAChannel.setTransferLength(gRxNumBytes);
call RxDMAChannel.run(TRUE);
}
else{
if(gNumRxFifoOverruns>0){
trace(DBG_USR1,"Num ROR's = %d\r\n",gNumRxFifoOverruns);
}
closeRxPort();
}
return;
}
void configureTxDMA(uint8_t *TxBuffer, uint16_t NumBytes){
call TxDMAChannel.setSourceAddr((uint32_t)TxBuffer);
call TxDMAChannel.setTargetAddr(MYFIFOADDR);
call TxDMAChannel.enableSourceAddrIncrement(TRUE);
call TxDMAChannel.enableTargetAddrIncrement(FALSE);
call TxDMAChannel.enableSourceFlowControl(FALSE);
call TxDMAChannel.enableTargetFlowControl(TRUE);
call TxDMAChannel.setTransferLength(NumBytes);
call TxDMAChannel.setMaxBurstSize(DMA_16ByteBurst);
call TxDMAChannel.setTransferWidth(DMA_4ByteWidth);
}
command result_t BulkTxRx.BulkTransmit(uint8_t *TxBuffer, uint16_t NumBytes){
if(openTxPort(TRUE)==FAIL){
//port was already open
return FAIL;
}
//port has now been opened
atomic{
gTxBuffer = TxBuffer;
gTxNumBytes = NumBytes;
}
//flush the data back to memory
cleanDCache(TxBuffer, NumBytes);
//invalidateDCache(TxBuffer, NumBytes);
configureTxDMA(TxBuffer,NumBytes);
//request a non-permanent channel
call TxDMAChannel.requestChannel(DMAID_MYUART_TX,DEFAULTDMATXPRIORITY, FALSE);
return SUCCESS;
}
event result_t TxDMAChannel.requestChannelDone(){
//so we've successfully been cleared to start doing something with our port...go!!
call TxDMAChannel.run(TRUE);
return SUCCESS;
}
async event void TxDMAChannel.Interrupt(){
gTxBuffer = signal BulkTxRx.BulkTransmitDone(gTxBuffer,
gTxNumBytes);
if(gTxBuffer){
//we want to do another write of gTxNumBytes)
//we should still have our DMA channel, so just all set size and run!
cleanDCache(gTxBuffer, gTxNumBytes);
call TxDMAChannel.setSourceAddr((uint32_t)gTxBuffer);
call TxDMAChannel.setTransferLength(gTxNumBytes);
call TxDMAChannel.run(TRUE);
}
else{
closeTxPort();
}
return;
}
command result_t BulkTxRx.BulkTxRx(BulkTxRxBuffer_t *TxRxBuffer, uint16_t NumBytes){
//this mode is not supported by a UART
return FAIL;
}
async event void UARTInterrupt.fired(){
uint8_t error,intSource = STIIR;
intSource = (intSource >> 1) & 0x3;
switch(intSource){
case 0:
//MODEM STATUS
break;
case 1:
//TRANSMIT FIFO Wants data
// signal UART.putDone();
break;
case 2:
//Received Data Available
while(_LSR & LSR_DR){
//signal UART.get(STRBR);
}
break;
case 3:
//Receive Error
error = _LSR;
break;
}
return;
}
--- NEW FILE: sched.c ---
// $Id: sched.c,v 1.1 2006/10/10 01:18:37 lnachman Exp $
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/*
*
* Authors: Jason Hill, Philip Levis
* Revision: $Id: sched.c,v 1.1 2006/10/10 01:18:37 lnachman Exp $
* Modifications: Removed unecessary code, cleanup.(5/30/02)
*
* Moved from non-blocking list to simple
* critical section. Changed task queue to
* length 8 (more efficient). (3/10/02)
*/
/*
* Scheduling data structures
*
* There is a list of size MAX_TASKS, stored as an cyclic array buffer.
* TOSH_sched_full is the index of first used slot (head of list).
* TOSH_sched_free is the index of first free slot (after tail of list).
* If free equals full, the list is empty.
* The list keeps at least one empty slot; one cannot add a task if
* advancing free would make it equal to full.
*
* Each entry consists of a task function pointer.
*
*/
typedef struct {
void (*tp) ();
} TOSH_sched_entry_T;
enum {
#ifdef TOSH_MAX_TASKS_LOG2
#if TOSH_MAX_TASKS_LOG2 > 8
#error "Maximum of 256 tasks, TOSH_MAX_TASKS_LOG2 must be <= 8"
#endif
TOSH_MAX_TASKS = 1 << TOSH_MAX_TASKS_LOG2,
#else
TOSH_MAX_TASKS = 8,
#endif
TOSH_TASK_BITMASK = (TOSH_MAX_TASKS - 1)
};
volatile TOSH_sched_entry_T TOSH_queue[TOSH_MAX_TASKS];
uint8_t TOSH_sched_full;
volatile uint8_t TOSH_sched_free;
#ifdef TASK_QUEUE_DEBUG
uint8_t max_occupancy;
uint8_t occupancy;
uint32_t failed_post;
#endif
void TOSH_sched_init(void)
{
int i;
TOSH_sched_free = 0;
TOSH_sched_full = 0;
for (i = 0; i < TOSH_MAX_TASKS; i++)
TOSH_queue[i].tp = NULL;
#ifdef TASK_QUEUE_DEBUG
max_occupancy = 0;
occupancy = 0;
failed_post = 0;
#endif
}
bool TOS_post(void (*tp) ());
#ifndef NESC_BUILD_BINARY
/*
* TOS_post (thread_pointer)
*
* Put the task pointer into the next free slot.
* Return 1 if successful, 0 if there is no free slot.
*
* This function uses a critical section to protect TOSH_sched_free.
* As tasks can be posted in both interrupt and non-interrupt context,
* this is necessary.
*/
bool TOS_post(void (*tp) ()) __attribute__((spontaneous)) {
__nesc_atomic_t fInterruptFlags;
uint8_t tmp;
// dbg(DBG_SCHED, ("TOSH_post: %d 0x%x\n", TOSH_sched_free, (int)tp));
fInterruptFlags = __nesc_atomic_start();
tmp = TOSH_sched_free;
if (TOSH_queue[tmp].tp == NULL) {
#ifdef TASK_QUEUE_DEBUG
occupancy++;
if (occupancy > max_occupancy) {
max_occupancy = occupancy;
}
#endif
TOSH_sched_free = (tmp + 1) & TOSH_TASK_BITMASK;
TOSH_queue[tmp].tp = tp;
__nesc_atomic_end(fInterruptFlags);
return TRUE;
}
else {
#ifdef TASK_QUEUE_DEBUG
failed_post++;
#endif
__nesc_atomic_end(fInterruptFlags);
return FALSE;
}
}
#endif
/*
* TOSH_schedule_task()
*
* Remove the task at the head of the queue and execute it, freeing
* the queue entry. Return 1 if a task was executed, 0 if the queue
* is empty.
*/
bool TOSH_run_next_task ()
{
__nesc_atomic_t fInterruptFlags;
uint8_t old_full;
void (*func)(void);
fInterruptFlags = __nesc_atomic_start();
old_full = TOSH_sched_full;
func = TOSH_queue[old_full].tp;
if (func == NULL)
{
__nesc_atomic_sleep();
return 0;
}
#ifdef TASK_QUEUE_DEBUG
occupancy--;
#endif
TOSH_queue[old_full].tp = NULL;
TOSH_sched_full = (old_full + 1) & TOSH_TASK_BITMASK;
__nesc_atomic_end(fInterruptFlags);
func();
return 1;
}
void TOSH_run_task() {
for (;;)
TOSH_run_next_task();
}
void TOSH_reset_debug_counters() {
__nesc_atomic_t fInterruptFlags;
#ifdef TASK_QUEUE_DEBUG
fInterruptFlags = __nesc_atomic_start();
max_occupancy = 0;
__nesc_atomic_end(fInterruptFlags);
#endif
}
void TOSH_get_debug_counters(uint8_t *mo, uint32_t *fp) {
#ifdef TASK_QUEUE_DEBUG
*mo = max_occupancy;
*fp = failed_post;
#endif
}
- Next message: [Tinyos-beta-commits] CVS: tinyos-1.x/beta/platform/imote2
BluSHC.nc, 1.4, 1.5 BluSHM.nc, 1.8, 1.9 BulkTxRx.nc, 1.2,
1.3 FlashM.nc, 1.12, 1.13 HPLCC2420M.nc, 1.8,
1.9 HPLFFUARTC.nc, 1.1, 1.2 HPLFFUARTM.nc, 1.3,
1.4 HPLSTUARTC.nc, 1.1, 1.2 HPLSTUARTM.nc, 1.3,
1.4 HPLUSBClientGPIOM.nc, 1.4, 1.5 PMIC.nc, 1.2, 1.3 PMICC.nc,
1.1, 1.2 PMICM.nc, 1.3, 1.4 SSP.nc, 1.1, 1.2 SSP1C.nc, 1.2,
1.3 SSP1M.nc, 1.4, 1.5 SettingsC.nc, 1.2, 1.3 SettingsM.nc,
1.2, 1.3 TimerJiffyAsyncC.nc, 1.1, 1.2 hardware.h, 1.8,
1.9 pmic.h, 1.4, 1.5
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Tinyos-beta-commits
mailing list