* @author Ben Greenstein <ben@cs.ucla.edu>
* @author Jonathan Hui <jhui@archrock.com>
* @author Joe Polastre <info@moteiv.com>
+ * @author Mark Hays
* @version $Revision$ $Date$
*/
async command void DMA.setSingleMode() {
DMAxCTL &= ~( DMADT0 | DMADT1 | DMADT2 );
+ DMAxCTL |= DMA_SINGLE_TRANSFER;
}
async command void DMA.setBlockMode() {
DMAxCTL &= ~( DMADT0 | DMADT1 | DMADT2 );
- DMAxCTL |= DMADT0;
+ DMAxCTL |= DMA_BLOCK_TRANSFER;
}
async command void DMA.setBurstMode() {
DMAxCTL &= ~( DMADT0 | DMADT1 | DMADT2 );
- DMAxCTL |= DMADT1;
+ DMAxCTL |= DMA_BURST_BLOCK_TRANSFER;
}
async command void DMA.setRepeatedSingleMode() {
DMAxCTL &= ~( DMADT0 | DMADT1 | DMADT2 );
- DMAxCTL |= DMADT2;
+ DMAxCTL |= DMA_REPEATED_SINGLE_TRANSFER;
}
async command void DMA.setRepeatedBlockMode() {
DMAxCTL &= ~( DMADT0 | DMADT1 | DMADT2 );
- DMAxCTL |= ( DMADT2 | DMADT0 );
+ DMAxCTL |= DMA_REPEATED_BLOCK_TRANSFER;
}
async command void DMA.setRepeatedBurstMode() {
DMAxCTL &= ~( DMADT0 | DMADT1 | DMADT2 );
- DMAxCTL |= ( DMADT2 | DMADT1 );
+ DMAxCTL |= DMA_REPEATED_BURST_BLOCK_TRANSFER;
}
async command void DMA.setSrcNoIncrement() {
DMAxCTL &= ~( DMASRCINCR0 | DMASRCINCR1 );
+ DMAxCTL |= DMA_ADDRESS_UNCHANGED;
}
async command void DMA.setSrcDecrement() {
- DMAxCTL |= DMASRCINCR1;
+ DMAxCTL &= ~( DMASRCINCR0 | DMASRCINCR1 );
+ DMAxCTL |= DMA_ADDRESS_DECREMENTED;
}
async command void DMA.setSrcIncrement() {
- DMAxCTL |= ( DMASRCINCR0 | DMASRCINCR1 );
+ DMAxCTL &= ~( DMASRCINCR0 | DMASRCINCR1 );
+ DMAxCTL |= DMA_ADDRESS_INCREMENTED;
}
async command void DMA.setDstNoIncrement() {
DMAxCTL &= ~( DMADSTINCR0 | DMADSTINCR1 );
+ DMAxCTL |= DMA_ADDRESS_UNCHANGED;
}
async command void DMA.setDstDecrement() {
- DMAxCTL |= DMADSTINCR1;
+ DMAxCTL &= ~( DMADSTINCR0 | DMADSTINCR1 );
+ DMAxCTL |= DMA_ADDRESS_DECREMENTED;
}
async command void DMA.setDstIncrement() {
- DMAxCTL |= ( DMADSTINCR0 | DMADSTINCR1 );
+ DMAxCTL &= ~( DMADSTINCR0 | DMADSTINCR1 );
+ DMAxCTL |= DMA_ADDRESS_INCREMENTED;
}
async command void DMA.setWordToWord() {
DMAxCTL &= ~(DMASRCBYTE | DMADSTBYTE);
DMAxCTL |= DMASWDW;
}
+
async command void DMA.setByteToWord() {
DMAxCTL &= ~(DMASRCBYTE | DMADSTBYTE);
DMAxCTL |= DMASBDW;
}
+
async command void DMA.setWordToByte() {
DMAxCTL &= ~(DMASRCBYTE | DMADSTBYTE);
DMAxCTL |= DMASWDB;
}
+
async command void DMA.setByteToByte() {
DMAxCTL &= ~(DMASRCBYTE | DMADSTBYTE);
DMAxCTL |= DMASBDB;
}
async command void DMA.enableInterrupt() {
- DMAxCTL |= DMAIE;
+ DMAxCTL |= DMAIE;
}
async command void DMA.disableInterrupt() {
- DMAxCTL &= ~DMAIE;
+ DMAxCTL &= ~DMAIE;
}
async command bool DMA.interruptPending() {
DMAxSA = (uint16_t)src;
DMAxDA = (uint16_t)dest;
DMAxSZ = size;
- DMACTL0 = ( DMACTL0 & ~DMAxTSEL_mask ) | ( t << DMAxTSEL_shift );
+ call DMA.setTrigger((dma_trigger_t) t);
DMAxCTL = s;
}
DMAxDA = 0;
DMAxSZ = 0;
}
-
-
}
/**
* @author Ben Greenstein <ben@cs.ucla.edu>
* @author Jonathan Hui <jhui@archrock.com>
+ * @author Mark Hays
* $Revision$ $Date$
*/
#ifndef MSP430DMA_H
#define MSP430DMA_H
+// General stuff
enum {
DMA_CHANNELS = 3
};
+
enum {
DMA_CHANNEL0 = 0,
DMA_CHANNEL1 = 1,
DMA_CHANNEL2 = 2,
DMA_CHANNEL_UNKNOWN = 3
};
+
enum {
DMA_CHANNEL_AVAILABLE = 0,
- DMA_CHANNEL_IN_USE = 1
+ DMA_CHANNEL_IN_USE = 1
};
-// HPL constants
-
+////////////////////////////////////////
+// Per-channel fields in DMACTL0
enum {
DMA0TSEL_SHIFT = 0,
DMA1TSEL_SHIFT = 4,
DMA1TSEL_MASK = ( 0xf0 ),
DMA2TSEL_MASK = ( 0xf00 ),
};
-enum {
- DMASRCINCR_SHIFT = (8),
- DMADSTINCR_SHIFT = (10),
- DMAINCR_MASK = (0x3)
-};
-enum {
- DMADT_SHIFT = (12),
- DMADT_MASK = (0x3)
-};
+
+// Per-field (channel) in DMACTL0
typedef enum {
DMA_TRIGGER_DMAREQ = 0x0, // software trigger
DMA_TRIGGER_TACCR2 = 0x1,
DMA_TRIGGER_TBCCR2 = 0x2,
- DMA_TRIGGER_USARTRX = 0x3, // URXIFG0 (UART/SPI), data received (I2C)
- DMA_TRIGGER_USARTTX = 0x4, // UTXIFG0 (UART/SPI), transmit ready (I2C)
+ DMA_TRIGGER_URXIFG0 = 0x3, // RX on USART0 (UART/SPI)
+ DMA_TRIGGER_UTXIFG0 = 0x4, // TX on USART0 (UART/SPI)
DMA_TRIGGER_DAC12IFG = 0x5, // DAC12_0CTL DAC12IFG bit
DMA_TRIGGER_ADC12IFGx = 0x6,
DMA_TRIGGER_TACCR0 = 0x7, // CCIFG bit
DMA_TRIGGER_TBCCR0 = 0x8, // CCIFG bit
- DMA_TRIGGER_URXIFG1 = 0x9,
- DMA_TRIGGER_UTXIFG1 = 0xa,
+ DMA_TRIGGER_URXIFG1 = 0x9, // RX on USART1 (UART/SPI)
+ DMA_TRIGGER_UTXIFG1 = 0xa, // TX on USART1 (UART/SPI)
DMA_TRIGGER_MULT = 0xb, // Hardware Multiplier Ready
DMA_TRIGGER_DMAxIFG = 0xe, // DMA0IFG triggers DMA channel 1
// DMA1IFG triggers DMA channel 2
DMA_TRIGGER_DMAE0 = 0xf // External Trigger DMAE0
} dma_trigger_t;
+typedef struct dma_channel_trigger_s {
+ unsigned int trigger : 4;
+ unsigned int reserved : 12;
+} __attribute__ ((packed)) dma_channel_trigger_t;
+
+////////////////////////////////////////
+// Bits in DMACTL1
enum {
DISABLE_NMI = 0,
- ENABLE_NMI = 1
+ ENABLE_NMI = 1,
};
enum {
NOT_ROUND_ROBIN = 0,
- ROUND_ROBIN = 1,
+ ROUND_ROBIN = 1,
};
enum {
NOT_ON_FETCH = 0,
- ON_FETCH = 1
+ ON_FETCH = 1,
};
-typedef enum {
- DMA_EDGE_SENSITIVE = 0x0,
- DMA_LEVEL_SENSITIVE = 0x1
-} dma_level_t;
+typedef struct dma_state_s {
+ unsigned int enableNMI : 1;
+ unsigned int roundRobin : 1;
+ unsigned int onFetch : 1;
+ unsigned int reserved : 13;
+} __attribute__ ((packed)) dma_state_t;
+
+////////////////////////////////////////
+// Stuff in DMAxCTL
+
+// DMADTx
+enum {
+ DMADT_SHIFT = 12,
+ DMADT_MASK = 0x7,
+};
typedef enum {
- DMA_WORD = 0x0,
- DMA_BYTE = 0x1
-} dma_byte_t;
+ DMA_SINGLE_TRANSFER = 0x0,
+ DMA_BLOCK_TRANSFER = 0x1,
+ DMA_BURST_BLOCK_TRANSFER = 0x2,
+ DMA_REPEATED_SINGLE_TRANSFER = 0x4,
+ DMA_REPEATED_BLOCK_TRANSFER = 0x5,
+ DMA_REPEATED_BURST_BLOCK_TRANSFER = 0x7
+} dma_transfer_mode_t;
+
+// DMA{SRC,DST}INCRx
+enum {
+ DMASRCINCR_SHIFT = 8,
+ DMADSTINCR_SHIFT = 10,
+ DMAINCR_MASK = 0x3,
+};
typedef enum {
- DMA_ADDRESS_UNCHANGED = 0x0,
+ DMA_ADDRESS_UNCHANGED = 0x0,
DMA_ADDRESS_DECREMENTED = 0x2,
DMA_ADDRESS_INCREMENTED = 0x3
} dma_incr_t;
typedef enum {
- DMA_SINGLE_TRANSFER = 0x0,
- DMA_BLOCK_TRANSFER = 0x1,
- DMA_BURST_BLOCK_TRANSFER = 0x2,
- DMA_REPEATED_SINGLE_TRANSFER = 0x4,
- DMA_REPEATED_BLOCK_TRANSFER = 0x5,
- DMA_REPEATED_BURST_BLOCK_TRANSFER = 0x7
-} dma_transfer_mode_t;
-
-typedef struct dma_state_s {
- unsigned int enableNMI : 1;
- unsigned int roundRobin : 1;
- unsigned int onFetch : 1;
- unsigned int reserved : 13;
-} __attribute__ ((packed)) dma_state_t;
+ DMA_WORD = 0x0,
+ DMA_BYTE = 0x1
+} dma_byte_t;
-typedef struct dma_channel_trigger_s {
- unsigned int trigger : 4;
- unsigned int reserved : 12;
-} __attribute__ ((packed)) dma_channel_trigger_t;
+// DMALEVEL
+typedef enum {
+ DMA_EDGE_SENSITIVE = 0x0,
+ DMA_LEVEL_SENSITIVE = 0x1
+} dma_level_t;
typedef struct dma_channel_state_s {
unsigned int request : 1;
} __attribute__ ((packed)) dma_channel_state_t;
#endif
+
* place of Msp430SpiNoDma0P.
*
* @author Jonathan Hui <jhui@archedrock.com>
+ * @author Mark Hays
* @version $Revision$ $Date$
*/
CLIENT_ID = unique( MSP430_SPIO_BUS ),
};
+#ifdef ENABLE_SPI0_DMA
+#warning "Enabling SPI DMA on USART0"
+ components Msp430SpiDma0P as SpiP;
+#else
components Msp430SpiNoDma0P as SpiP;
+#endif
+
Resource = SpiP.Resource[ CLIENT_ID ];
SpiByte = SpiP.SpiByte;
SpiPacket = SpiP.SpiPacket[ CLIENT_ID ];
* place of Msp430SpiNoDma0P.
*
* @author Jonathan Hui <jhui@archedrock.com>
+ * @author Mark Hays
* @version $Revision$ $Date$
*/
CLIENT_ID = unique( MSP430_SPI1_BUS ),
};
+#ifdef ENABLE_SPI1_DMA
+#warning "Enabling SPI DMA on USART1"
+ components Msp430SpiDma1P as SpiP;
+#else
components Msp430SpiNoDma1P as SpiP;
+#endif
+
Resource = SpiP.Resource[ CLIENT_ID ];
SpiByte = SpiP.SpiByte;
SpiPacket = SpiP.SpiPacket[ CLIENT_ID ];
/**
* @author Jonathan Hui <jhui@archedrock.com>
+ * @author Mark Hays
* @version $Revision$ $Date$
*/
implementation {
- components new Msp430SpiDmaP() as SpiP;
+#include "Msp430Dma.h"
+
+ components new Msp430SpiDmaP(IFG1_,
+ U0TXBUF_,
+ UTXIFG0,
+ (uint16_t) DMA_TRIGGER_UTXIFG0,
+ U0RXBUF_,
+ URXIFG0,
+ (uint16_t) DMA_TRIGGER_URXIFG0) as SpiP;
Resource = SpiP.Resource;
ResourceConfigure = SpiP.ResourceConfigure;
Msp430SpiConfigure = SpiP.Msp430SpiConfigure;
/**
* @author Jonathan Hui <jhui@archedrock.com>
+ * @author Mark Hays
* @version $Revision$ $Date$
*/
configuration Msp430SpiDma1P {
provides interface Resource[ uint8_t id ];
- provides interface ResourceControl [uint8_t id];
+ provides interface ResourceConfigure[uint8_t id];
provides interface SpiByte;
provides interface SpiPacket[ uint8_t id ];
implementation {
- components new Msp430SpiDmaP() as SpiP;
+#include "Msp430Dma.h"
+
+ components new Msp430SpiDmaP(IFG2_,
+ U1TXBUF_,
+ UTXIFG1,
+ (uint16_t) DMA_TRIGGER_UTXIFG1,
+ U1RXBUF_,
+ URXIFG1,
+ (uint16_t) DMA_TRIGGER_URXIFG1) as SpiP;
Resource = SpiP.Resource;
- ResourceControl = SpiP.ResourceControl;
+ ResourceConfigure = SpiP.ResourceConfigure;
Msp430SpiConfigure = SpiP.Msp430SpiConfigure;
SpiByte = SpiP.SpiByte;
SpiPacket = SpiP.SpiPacket;
/**
* @author Jonathan Hui <jhui@archedrock.com>
+ * @author Mark Hays
* @version $Revision$ $Date$
*/
-generic module Msp430SpiDmaP() {
+generic module Msp430SpiDmaP( uint16_t IFG_addr,
+ uint16_t TXBUF_addr,
+ uint8_t TXIFG,
+ uint16_t TXTRIG,
+ uint16_t RXBUF_addr,
+ uint8_t RXIFG,
+ uint16_t RXTRIG ) {
provides interface Resource[ uint8_t id ];
provides interface ResourceConfigure[ uint8_t id ];
implementation {
- MSP430REG_NORACE( IFG1 );
+#define IFG (*(volatile uint8_t*)IFG_addr)
uint8_t* m_tx_buf;
uint8_t* m_rx_buf;
uint8_t* rx_buf,
uint16_t len ) {
- uint16_t ctrl;
-
atomic {
m_client = id;
m_tx_buf = tx_buf;
m_len = len;
}
- if ( rx_buf ) {
- ctrl = 0xcd4;
- }
- else {
- ctrl = 0x0d4;
- rx_buf = &m_dump;
- }
-
if ( len ) {
- IFG1 &= ~( UTXIFG0 | URXIFG0 );
- call DmaChannel1.setupTransferRaw( ctrl, DMA_TRIGGER_USARTRX,
- (uint16_t*)U0RXBUF_, rx_buf, len );
- call DmaChannel2.setupTransferRaw( 0x3d4, DMA_TRIGGER_USARTTX,
- tx_buf, (uint16_t*)U0TXBUF_, len );
- IFG1 |= UTXIFG0;
- }
- else {
+ // clear the interrupt flags
+ IFG &= ~( TXIFG | RXIFG );
+
+ // set up the RX xfer
+ call DmaChannel1.setupTransfer(DMA_SINGLE_TRANSFER,
+ RXTRIG,
+ DMA_EDGE_SENSITIVE,
+ (void *) RXBUF_addr,
+ rx_buf ? rx_buf : &m_dump,
+ len,
+ DMA_BYTE,
+ DMA_BYTE,
+ DMA_ADDRESS_UNCHANGED,
+ rx_buf ?
+ DMA_ADDRESS_INCREMENTED :
+ DMA_ADDRESS_UNCHANGED);
+ // this doesn't start a transfer; it simply enables the channel
+ call DmaChannel1.startTransfer();
+
+ // set up the TX xfer
+ call DmaChannel2.setupTransfer(DMA_SINGLE_TRANSFER,
+ TXTRIG,
+ DMA_EDGE_SENSITIVE,
+ tx_buf,
+ (void *) TXBUF_addr,
+ len,
+ DMA_BYTE,
+ DMA_BYTE,
+ DMA_ADDRESS_INCREMENTED,
+ DMA_ADDRESS_UNCHANGED);
+ // this doesn't start a transfer; it simply enables the channel
+ call DmaChannel2.startTransfer();
+
+ // pong the tx flag to get things rolling
+ IFG |= TXIFG;
+ } else {
post signalDone_task();
}