Browse Source

DMAChannel stuff (getting close to final)

teensy4-core
PaulStoffregen 10 years ago
parent
commit
a9d19478dd
1 changed files with 33 additions and 15 deletions
  1. +33
    -15
      teensy3/DMAChannel.h

+ 33
- 15
teensy3/DMAChannel.h View File

/*************************************************/ /*************************************************/


// Set the data size used for each triggered transfer // Set the data size used for each triggered transfer
void size(unsigned int len) {
void transferSize(unsigned int len) {
if (len == 4) { if (len == 4) {
TCD->NBYTES = 4; TCD->NBYTES = 4;
if (TCD->SOFF != 0) TCD->SOFF = 4; if (TCD->SOFF != 0) TCD->SOFF = 4;
} }


// Set the number of transfers (number of triggers until complete) // Set the number of transfers (number of triggers until complete)
void count(unsigned int len) {
void transferCount(unsigned int len) {
if (len > 32767) return; if (len > 32767) return;
if (len >= 512) { if (len >= 512) {
TCD->BITER = len; TCD->BITER = len;


void replaceSettingsOnCompletion(const DMABaseClass &settings) { void replaceSettingsOnCompletion(const DMABaseClass &settings) {
TCD->DLASTSGA = (int32_t)(settings.TCD); TCD->DLASTSGA = (int32_t)(settings.TCD);
TCD->CSR &= ~DMA_TCD_CSR_DONE;
TCD->CSR |= DMA_TCD_CSR_ESG; TCD->CSR |= DMA_TCD_CSR_ESG;
} }


/***************************************/ /***************************************/


// Triggers cause the DMA channel to actually move data. Each // Triggers cause the DMA channel to actually move data. Each
// trigger moves a single data unit, which is typically 8, 16 or 32 bits.
// trigger moves a single data unit, which is typically 8, 16 or
// 32 bits. If a channel is configured for 200 transfers


// Use a hardware trigger to make the DMA channel run // Use a hardware trigger to make the DMA channel run
void attachTrigger(uint8_t source) {
void triggerAtHardwareEvent(uint8_t source) {
volatile uint8_t *mux; volatile uint8_t *mux;
mux = (volatile uint8_t *)&(DMAMUX0_CHCFG0) + channel; mux = (volatile uint8_t *)&(DMAMUX0_CHCFG0) + channel;
*mux = 0; *mux = 0;
// Use another DMA channel as the trigger, causing this // Use another DMA channel as the trigger, causing this
// channel to trigger after each transfer is makes, except // channel to trigger after each transfer is makes, except
// the its last transfer. This effectively makes the 2 // the its last transfer. This effectively makes the 2
// channels run in parallel.
void attachTriggerBeforeCompletion(DMABaseClass &ch) {
// channels run in parallel until the last transfer
void triggerAtTransfersOf(DMABaseClass &ch) {
ch.TCD->BITER = (ch.TCD->BITER & ~DMA_TCD_BITER_ELINKYES_LINKCH_MASK) ch.TCD->BITER = (ch.TCD->BITER & ~DMA_TCD_BITER_ELINKYES_LINKCH_MASK)
| DMA_TCD_BITER_ELINKYES_LINKCH(channel) | DMA_TCD_BITER_ELINKYES_ELINK; | DMA_TCD_BITER_ELINKYES_LINKCH(channel) | DMA_TCD_BITER_ELINKYES_ELINK;
ch.TCD->CITER = ch.TCD->BITER ; ch.TCD->CITER = ch.TCD->BITER ;


// Use another DMA channel as the trigger, causing this // Use another DMA channel as the trigger, causing this
// channel to trigger when the other channel completes. // channel to trigger when the other channel completes.
void attachTriggerAtCompletion(DMABaseClass &ch) {
ch.TCD->CSR = (ch.TCD->CSR & ~DMA_TCD_CSR_MAJORLINKCH_MASK)
void triggerAtCompletionOf(DMABaseClass &ch) {
ch.TCD->CSR = (ch.TCD->CSR & ~(DMA_TCD_CSR_MAJORLINKCH_MASK|DMA_TCD_CSR_DONE))
| DMA_TCD_CSR_MAJORLINKCH(channel) | DMA_TCD_CSR_MAJORELINK; | DMA_TCD_CSR_MAJORLINKCH(channel) | DMA_TCD_CSR_MAJORELINK;
} }


// Cause this DMA channel to be continuously triggered, so // Cause this DMA channel to be continuously triggered, so
// it will move data as rapidly as possible, without waiting. // it will move data as rapidly as possible, without waiting.
// Normally this would be used with disableOnCompletion(). // Normally this would be used with disableOnCompletion().
void attachTriggerContinuous(void) {
void triggerContinuously(void) {
volatile uint8_t *mux = (volatile uint8_t *)&DMAMUX0_CHCFG0; volatile uint8_t *mux = (volatile uint8_t *)&DMAMUX0_CHCFG0;
mux[channel] = 0; mux[channel] = 0;
#if DMAMUX_NUM_SOURCE_ALWAYS >= DMA_NUM_CHANNELS #if DMAMUX_NUM_SOURCE_ALWAYS >= DMA_NUM_CHANNELS
} }


// Manually trigger the DMA channel. // Manually trigger the DMA channel.
void trigger(void) {
void triggerManual(void) {
DMA_SSRT = channel; DMA_SSRT = channel;
} }


void enable(void) { void enable(void) {
DMA_SERQ = channel; DMA_SERQ = channel;
} }

void disable(void) { void disable(void) {
DMA_CERQ = channel; DMA_CERQ = channel;
} }




/***************************************/ /***************************************/
/** Status **/ /** Status **/
/***************************************/ /***************************************/


// TODO: "get" functions, to read important stuff, like SADDR & DADDR...
// error status, etc
bool complete(void) {
if (TCD->CSR & DMA_TCD_CSR_DONE) return true;
return false;
}
void clearComplete(void) {
DMA_CDNE = channel;
}
bool error(void) {
if (DMA_ERR & (1<<channel)) return true;
return false;
}
void clearError(void) {
DMA_CERR = channel;
}
void * sourceAddress(void) {
return (void *)(TCD->SADDR);
}
void * destinationAddress(void) {
return (void *)(TCD->DADDR);
}


/***************************************/ /***************************************/
/** Direct Hardware Access **/ /** Direct Hardware Access **/
// can be used directly. This leads to less portable and less readable // can be used directly. This leads to less portable and less readable
// code, but direct control of all parameters is possible. // code, but direct control of all parameters is possible.
uint8_t channel; uint8_t channel;
// TCD is accessible due to inheritance from DMABaseClass


/* usage cases: /* usage cases:



Loading…
Cancel
Save