Skip to content

Commit

Permalink
Refactored disabling ADC DMA
Browse files Browse the repository at this point in the history
  • Loading branch information
dc42 committed Apr 11, 2021
1 parent 538e48f commit c575f39
Showing 1 changed file with 20 additions and 26 deletions.
46 changes: 20 additions & 26 deletions src/SAME5x_C21/SAME5x/AnalogIn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class alignas(16) AdcClass
{
noChannels = 0,
starting,
idle,
converting,
ready
};
Expand All @@ -84,6 +83,7 @@ class alignas(16) AdcClass
private:
bool InternalEnableChannel(unsigned int chan, AnalogInCallbackFunction fn, CallbackParameter param, uint32_t p_ticksPerCall) noexcept;
size_t GetChannel(size_t slot) noexcept { return inputRegisters[DmaDwordsPerChannel * slot] & 0x1F; }
void DisableDma() noexcept;
void ReInit() noexcept;

static void DmaCompleteCallback(CallbackParameter cp, DmaCallbackReason reason) noexcept;
Expand Down Expand Up @@ -132,8 +132,7 @@ void AdcClass::Exit() noexcept
{
taskToWake = nullptr;
DmacManager::DisableCompletedInterrupt(dmaChan + 1); // disable the reader completed interrupt
DmacManager::DisableChannel(dmaChan); // disable the sequencer DMA
DmacManager::DisableChannel(dmaChan + 1); // disable the reader DMA too
DisableDma();
}

// Try to enable this ADC on the specified channel returning true if successful
Expand Down Expand Up @@ -182,18 +181,23 @@ bool AdcClass::EnableTemperatureSensor(unsigned int sensorNumber, AnalogInCallba
return InternalEnableChannel(sensorNumber + ADC_INPUTCTRL_MUXPOS_PTAT_Val, fn, param, p_ticksPerCall);
}

void AdcClass::DisableDma() noexcept
{
#if ADC_DEBUG
if (!DmacManager::DisableChannel(dmaChan)) { ++rxDmaNotDisabledErrs; }
if (!DmacManager::DisableChannel(dmaChan + 1)) { ++txDmaNotDisabledErrs; }
#else
DmacManager::DisableChannel(dmaChan);
DmacManager::DisableChannel(dmaChan + 1);
#endif
}

// Initialise or re-initialise the ADC and DMA channels. The ADC clock has already been enabled.
void AdcClass::ReInit() noexcept
{
if (!hri_adc_is_syncing(device, ADC_SYNCBUSY_SWRST))
{
if (hri_adc_get_CTRLA_reg(device, ADC_CTRLA_ENABLE))
{
hri_adc_clear_CTRLA_ENABLE_bit(device);
hri_adc_wait_for_sync(device, ADC_SYNCBUSY_ENABLE);
}
hri_adc_write_CTRLA_reg(device, ADC_CTRLA_SWRST);
}
DisableDma();

hri_adc_write_CTRLA_reg(device, ADC_CTRLA_SWRST);
hri_adc_wait_for_sync(device, ADC_SYNCBUSY_SWRST);

// From the SAME5x errata:
Expand Down Expand Up @@ -251,15 +255,14 @@ void AdcClass::ReInit() noexcept
hri_supc_set_VREF_TSEN_bit(SUPC);
hri_supc_clear_VREF_VREFOE_bit(SUPC);


// Initialise the DMAC. First the sequencer
DmacManager::DisableChannel(dmaChan);
DmacManager::SetDestinationAddress(dmaChan, &device->DSEQDATA.reg);
DmacManager::SetBtctrl(dmaChan, DMAC_BTCTRL_VALID | DMAC_BTCTRL_EVOSEL_DISABLE | DMAC_BTCTRL_BLOCKACT_INT | DMAC_BTCTRL_BEATSIZE_WORD
| DMAC_BTCTRL_SRCINC | DMAC_BTCTRL_STEPSEL_SRC | DMAC_BTCTRL_STEPSIZE_X1);
DmacManager::SetTriggerSource(dmaChan, (DmaTrigSource)((uint8_t)trigSrc + 1));

// Now the result reader
DmacManager::DisableChannel(dmaChan + 1);
DmacManager::SetSourceAddress(dmaChan + 1, const_cast<uint16_t *>(&device->RESULT.reg));
DmacManager::SetInterruptCallback(dmaChan + 1, DmaCompleteCallback, this);
DmacManager::SetBtctrl(dmaChan + 1, DMAC_BTCTRL_VALID | DMAC_BTCTRL_EVOSEL_DISABLE | DMAC_BTCTRL_BLOCKACT_INT | DMAC_BTCTRL_BEATSIZE_HWORD
Expand Down Expand Up @@ -317,9 +320,6 @@ bool AdcClass::StartConversion() noexcept
return false; // let the current conversion continue
}

DmacManager::DisableChannel(dmaChan + 1);
DmacManager::DisableChannel(dmaChan);

++conversionTimeouts;
ReInit();
}
Expand All @@ -328,13 +328,8 @@ bool AdcClass::StartConversion() noexcept
taskToWake = TaskBase::GetCallerTaskHandle();

// Set up DMA sequencing of the ADC
#if ADC_DEBUG
if (!DmacManager::DisableChannel(dmaChan + 1)) { ++txDmaNotDisabledErrs; }
if (!DmacManager::DisableChannel(dmaChan)) { ++rxDmaNotDisabledErrs; }
#else
DmacManager::DisableChannel(dmaChan + 1);
DmacManager::DisableChannel(dmaChan);
#endif
DisableDma();
(void)device->RESULT.reg; // make sure no result pending (this is necessary to make it work!)

DmacManager::SetDestinationAddress(dmaChan + 1, results);
DmacManager::SetDataLength(dmaChan + 1, numEnabled);
Expand Down Expand Up @@ -404,10 +399,9 @@ void AdcClass::ResultReadyCallback(DmaCallbackReason reason) noexcept
? reason
: DmaCallbackReason::completeAndError;
#endif
DisableDma();
state = State::ready;
++conversionsCompleted;
DmacManager::DisableChannel(dmaChan); // disable the sequencer DMA
DmacManager::DisableChannel(dmaChan + 1); // disable the reader DMA
TaskBase::GiveFromISR(taskToWake);
}

Expand Down

0 comments on commit c575f39

Please sign in to comment.