Skip to content

Commit c947d65

Browse files
committed
fix bugs in samd51 ADC paths for register names
1 parent be91bf8 commit c947d65

2 files changed

Lines changed: 105 additions & 49 deletions

File tree

libraries/ADC/src/ADC.cpp

Lines changed: 98 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
#include <PendSV.h>
44
#include <wiring_private.h>
55

6+
#ifdef FAMILY_SAMD5X
7+
#ifndef NVMCTRL_TEMP_LOG
8+
#ifdef NVMCTRL_TEMP_LOG_W0
9+
#define NVMCTRL_TEMP_LOG NVMCTRL_TEMP_LOG_W0
10+
#endif
11+
#endif
12+
#endif
13+
614
static inline float decToFrac(uint8_t val) {
715
// Temperature fuse decimal part is 4 bits only (0-15):
816
// 0-9 represent tenths (0.0-0.9), 10-15 represent hundredths (0.10-0.15)
@@ -113,6 +121,34 @@ constexpr uint8_t kMaxAdjres = 4;
113121
constexpr uint8_t kAdcPendSvServiceId = PendSV::kMaxServices - 1;
114122
constexpr uint32_t kAdcNvicPriority = (1u << __NVIC_PRIO_BITS) - 1u;
115123

124+
#ifdef FAMILY_SAMD5X
125+
#ifdef ADC_EVCTRL_SYNCEI
126+
constexpr uint8_t kAdcEvctrlSynceiBit = ADC_EVCTRL_SYNCEI;
127+
#elif defined(ADC_EVCTRL_FLUSHEI)
128+
constexpr uint8_t kAdcEvctrlSynceiBit = ADC_EVCTRL_FLUSHEI;
129+
#else
130+
constexpr uint8_t kAdcEvctrlSynceiBit = 0u;
131+
#endif
132+
#else
133+
constexpr uint8_t kAdcEvctrlSynceiBit = ADC_EVCTRL_SYNCEI;
134+
#endif
135+
136+
uint8_t adcDmacResrdyTrigger() {
137+
#ifdef FAMILY_SAMD5X
138+
return ADC0_DMAC_ID_RESRDY;
139+
#else
140+
return ADC_DMAC_ID_RESRDY;
141+
#endif
142+
}
143+
144+
inline Adc *adcInstance() {
145+
#ifdef FAMILY_SAMD5X
146+
return ADC0;
147+
#else
148+
return ADC;
149+
#endif
150+
}
151+
116152
// ADC IRQ routing mirrors SERCOM family handling:
117153
// - SAMD2x exposes a single ADC_IRQn vector.
118154
// - SAME/SAMD5x splits ADC0 interrupts across two NVIC lines:
@@ -230,11 +266,14 @@ bool AdcEngine::begin() {
230266
return false;
231267
}
232268

233-
dma_.setTrigger(ADC_DMAC_ID_RESRDY);
269+
dma_.setTrigger(adcDmacResrdyTrigger());
234270
dma_.setAction(DMA_TRIGGER_ACTON_BEAT);
235271
dma_.setCallback(AdcEngine::dmaDoneCallback, DMA_CALLBACK_TRANSFER_DONE);
236-
dmaDescriptor_ = dma_.addDescriptor((void *)&ADC->RESULT.reg, (void *)&dmaLatestResult_, 1,
237-
DMA_BEAT_SIZE_HWORD, false, false);
272+
Adc *const adc = adcInstance();
273+
274+
dmaDescriptor_ =
275+
dma_.addDescriptor((void *)&adc->RESULT.reg, (void *)&dmaLatestResult_,
276+
1, DMA_BEAT_SIZE_HWORD, false, false);
238277
if (dmaDescriptor_ == nullptr) {
239278
dma_.free();
240279
PendSV::instance().clearService(kAdcPendSvServiceId);
@@ -249,8 +288,8 @@ bool AdcEngine::begin() {
249288
NVIC_EnableIRQ(irq);
250289
}
251290

252-
ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY | ADC_INTFLAG_WINMON;
253-
ADC->INTENSET.bit.RESRDY = 1;
291+
adc->INTFLAG.reg = ADC_INTFLAG_RESRDY | ADC_INTFLAG_WINMON;
292+
adc->INTENSET.bit.RESRDY = 1;
254293
initialized_ = true;
255294
return true;
256295
}
@@ -264,16 +303,19 @@ void AdcEngine::end() {
264303
NVIC_DisableIRQ(irq);
265304
NVIC_ClearPendingIRQ(irq);
266305
}
267-
ADC->INTENCLR.bit.RESRDY = 1;
306+
Adc *const adc = adcInstance();
307+
308+
adc->INTENCLR.bit.RESRDY = 1;
268309

269310
if (dmaActive_)
270311
dma_.abort();
271312

272313
dma_.free();
273314
dmaDescriptor_ = nullptr;
274315

275-
ADC->CTRLA.bit.SWRST = 1;
276-
while (ADC->CTRLA.bit.SWRST);
316+
adc->CTRLA.bit.SWRST = 1;
317+
while (adc->CTRLA.bit.SWRST)
318+
;
277319
waitAdcSync();
278320

279321
PendSV::instance().clearService(kAdcPendSvServiceId);
@@ -389,20 +431,22 @@ uint32_t AdcEngine::enabledMask() const {
389431
}
390432

391433
void AdcEngine::onResrdyIsr() {
392-
const uint8_t flags = static_cast<uint8_t>(ADC->INTFLAG.reg & 0x0F);
393-
394-
if ((flags & ADC_INTFLAG_WINMON) != 0u) {
395-
ChannelADC *channel = activeChannel_;
396-
if (channel != nullptr && channel->windowEnabled_ && channel->onWindowMonitor_ != nullptr) {
397-
const uint16_t result = ADC->RESULT.reg;
398-
channel->onWindowMonitor_(channel, result, channel->windowUserData_);
399-
}
434+
Adc *const adc = adcInstance();
435+
const uint8_t flags = static_cast<uint8_t>(adc->INTFLAG.reg & 0x0F);
436+
437+
if ((flags & ADC_INTFLAG_WINMON) != 0u) {
438+
ChannelADC *channel = activeChannel_;
439+
if (channel != nullptr && channel->windowEnabled_ &&
440+
channel->onWindowMonitor_ != nullptr) {
441+
const uint16_t result = adc->RESULT.reg;
442+
channel->onWindowMonitor_(channel, result, channel->windowUserData_);
400443
}
444+
}
401445

402446
if ((flags & ADC_INTFLAG_RESRDY) != 0u)
403-
ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;
447+
adc->INTFLAG.reg = ADC_INTFLAG_RESRDY;
404448

405-
ADC->INTFLAG.reg = 0x0F;
449+
adc->INTFLAG.reg = 0x0F;
406450
}
407451

408452
void AdcEngine::onPendSv() {
@@ -458,28 +502,30 @@ bool AdcEngine::applyChannelAndStart(ChannelADC *channel, bool monitorMode) {
458502
if (channel == nullptr)
459503
return false;
460504

461-
ADC->CTRLA.bit.ENABLE = 0;
505+
Adc *const adc = adcInstance();
506+
507+
adc->CTRLA.bit.ENABLE = 0;
462508
waitAdcSync();
463509

464510
const uint8_t refctrlReg = static_cast<uint8_t>(ADC_REFCTRL_REFSEL(channel->refSel_));
465-
ADC->REFCTRL.reg = refctrlReg;
511+
adc->REFCTRL.reg = refctrlReg;
466512

467513
#ifdef FAMILY_SAMD5X
468514
const uint16_t inputCtrlReg = static_cast<uint16_t>(
469515
ADC_INPUTCTRL_MUXPOS(channel->muxPos_) | ADC_INPUTCTRL_MUXNEG(channel->muxNeg_) |
470516
(channel->differentialMode_ ? ADC_INPUTCTRL_DIFFMODE : 0u));
471-
ADC->INPUTCTRL.reg = inputCtrlReg;
517+
adc->INPUTCTRL.reg = inputCtrlReg;
472518

473519
const uint8_t avgCtrlReg =
474520
static_cast<uint8_t>(ADC_AVGCTRL_SAMPLENUM(sampleNumToCode(channel->sampleNum_)) |
475521
ADC_AVGCTRL_ADJRES(channel->adjres_));
476-
ADC->AVGCTRL.reg = avgCtrlReg;
522+
adc->AVGCTRL.reg = avgCtrlReg;
477523

478-
uint16_t ctrlaReg = ADC->CTRLA.reg;
524+
uint16_t ctrlaReg = adc->CTRLA.reg;
479525
ctrlaReg =
480526
static_cast<uint16_t>((ctrlaReg & ~ADC_CTRLA_PRESCALER_Msk) |
481527
ADC_CTRLA_PRESCALER(static_cast<uint8_t>(channel->prescaler_)));
482-
ADC->CTRLA.reg = ctrlaReg;
528+
adc->CTRLA.reg = ctrlaReg;
483529

484530
const uint16_t ctrlbReg = static_cast<uint16_t>(
485531
(channel->leftAdjust_ ? ADC_CTRLB_LEFTADJ : 0u) |
@@ -489,30 +535,30 @@ bool AdcEngine::applyChannelAndStart(ChannelADC *channel, bool monitorMode) {
489535
ADC_CTRLB_WINMODE(channel->windowEnabled_
490536
? static_cast<uint8_t>(channel->winMode_)
491537
: static_cast<uint8_t>(AdcWinMode::ADC_WINMODE_DISABLE)));
492-
ADC->CTRLB.reg = ctrlbReg;
538+
adc->CTRLB.reg = ctrlbReg;
493539

494540
const uint8_t evctrlReg =
495541
static_cast<uint8_t>((channel->evWinmonEo_ ? ADC_EVCTRL_WINMONEO : 0u) |
496542
(channel->evResrdyEo_ ? ADC_EVCTRL_RESRDYEO : 0u) |
497-
(channel->evSyncei_ ? ADC_EVCTRL_SYNCEI : 0u) |
543+
(channel->evSyncei_ ? kAdcEvctrlSynceiBit : 0u) |
498544
(channel->evStartei_ ? ADC_EVCTRL_STARTEI : 0u));
499-
ADC->EVCTRL.reg = evctrlReg;
545+
adc->EVCTRL.reg = evctrlReg;
500546

501-
ADC->WINLT.reg = channel->windowLower_;
502-
ADC->WINUT.reg = channel->windowUpper_;
547+
adc->WINLT.reg = channel->windowLower_;
548+
adc->WINUT.reg = channel->windowUpper_;
503549

504-
ADC->OFFSETCORR.reg = static_cast<uint16_t>(channel->offsetCorr_);
505-
ADC->GAINCORR.reg = channel->gainCorr_;
550+
adc->OFFSETCORR.reg = static_cast<uint16_t>(channel->offsetCorr_);
551+
adc->GAINCORR.reg = channel->gainCorr_;
506552
#else
507553
const uint16_t inputCtrlReg = static_cast<uint16_t>(
508554
ADC_INPUTCTRL_MUXPOS(channel->muxPos_) | ADC_INPUTCTRL_MUXNEG(channel->muxNeg_) |
509555
ADC_INPUTCTRL_GAIN(static_cast<uint8_t>(channel->gain_)));
510-
ADC->INPUTCTRL.reg = inputCtrlReg;
556+
adc->INPUTCTRL.reg = inputCtrlReg;
511557

512558
const uint8_t avgCtrlReg =
513559
static_cast<uint8_t>(ADC_AVGCTRL_SAMPLENUM(sampleNumToCode(channel->sampleNum_)) |
514560
ADC_AVGCTRL_ADJRES(channel->adjres_));
515-
ADC->AVGCTRL.reg = avgCtrlReg;
561+
adc->AVGCTRL.reg = avgCtrlReg;
516562

517563
const uint16_t ctrlbReg =
518564
static_cast<uint16_t>((channel->differentialMode_ ? ADC_CTRLB_DIFFMODE : 0u) |
@@ -521,48 +567,49 @@ bool AdcEngine::applyChannelAndStart(ChannelADC *channel, bool monitorMode) {
521567
(channel->corrEnabled_ ? ADC_CTRLB_CORREN : 0u) |
522568
ADC_CTRLB_RESSEL(static_cast<uint8_t>(channel->ressel_)) |
523569
ADC_CTRLB_PRESCALER(static_cast<uint8_t>(channel->prescaler_)));
524-
ADC->CTRLB.reg = ctrlbReg;
570+
adc->CTRLB.reg = ctrlbReg;
525571

526572
const uint8_t evctrlReg =
527573
static_cast<uint8_t>((channel->evWinmonEo_ ? ADC_EVCTRL_WINMONEO : 0u) |
528574
(channel->evResrdyEo_ ? ADC_EVCTRL_RESRDYEO : 0u) |
529-
(channel->evSyncei_ ? ADC_EVCTRL_SYNCEI : 0u) |
575+
(channel->evSyncei_ ? kAdcEvctrlSynceiBit : 0u) |
530576
(channel->evStartei_ ? ADC_EVCTRL_STARTEI : 0u));
531-
ADC->EVCTRL.reg = evctrlReg;
577+
adc->EVCTRL.reg = evctrlReg;
532578

533-
ADC->WINLT.reg = channel->windowLower_;
534-
ADC->WINUT.reg = channel->windowUpper_;
579+
adc->WINLT.reg = channel->windowLower_;
580+
adc->WINUT.reg = channel->windowUpper_;
535581

536582
const uint8_t winctrlReg = static_cast<uint8_t>(
537583
ADC_WINCTRL_WINMODE(channel->windowEnabled_ ? static_cast<uint8_t>(channel->winMode_) : 0));
538-
ADC->WINCTRL.reg = winctrlReg;
584+
adc->WINCTRL.reg = winctrlReg;
539585

540-
ADC->OFFSETCORR.reg = static_cast<uint16_t>(channel->offsetCorr_);
541-
ADC->GAINCORR.reg = channel->gainCorr_;
586+
adc->OFFSETCORR.reg = static_cast<uint16_t>(channel->offsetCorr_);
587+
adc->GAINCORR.reg = channel->gainCorr_;
542588
#endif
543589

544590
waitAdcSync();
545591

546-
ADC->INTENCLR.reg = 0x0F;
592+
adc->INTENCLR.reg = 0x0F;
547593
const uint8_t intensetReg =
548594
static_cast<uint8_t>(ADC_INTENSET_RESRDY |
549595
((monitorMode && channel->windowEnabled_) ? ADC_INTENSET_WINMON : 0u));
550-
ADC->INTENSET.reg = intensetReg;
596+
adc->INTENSET.reg = intensetReg;
551597

552-
ADC->INTFLAG.reg = 0x0F;
598+
adc->INTFLAG.reg = 0x0F;
553599

554600
if (dmaDescriptor_ == nullptr)
555601
return false;
556602

557-
dma_.changeDescriptor(dmaDescriptor_, (void *)&ADC->RESULT.reg, (void *)&dmaLatestResult_, 1);
603+
dma_.changeDescriptor(dmaDescriptor_, (void *)&adc->RESULT.reg,
604+
(void *)&dmaLatestResult_, 1);
558605
if (dma_.startJob() != DMA_STATUS_OK)
559606
return false;
560607

561608
dmaActive_ = true;
562609
activeChannel_ = channel;
563610
activeMonitorMode_ = monitorMode;
564611

565-
ADC->CTRLA.bit.ENABLE = 1;
612+
adc->CTRLA.bit.ENABLE = 1;
566613
waitAdcSync();
567614
startConversion();
568615
return true;
@@ -586,10 +633,13 @@ bool AdcEngine::startMonitorIfIdle() {
586633
}
587634

588635
void AdcEngine::waitAdcSync() const {
636+
Adc *const adc = adcInstance();
589637
#ifdef FAMILY_SAMD5X
590-
while (ADC->SYNCBUSY.reg);
638+
while (adc->SYNCBUSY.reg)
639+
;
591640
#else
592-
while (ADC->STATUS.bit.SYNCBUSY);
641+
while (adc->STATUS.bit.SYNCBUSY)
642+
;
593643
#endif
594644
}
595645

libraries/ADC/src/ADC.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,13 @@ class AdcEngine {
219219
bool applyChannelAndStart(ChannelADC *channel, bool monitorMode = false);
220220
bool startMonitorIfIdle();
221221
void waitAdcSync() const;
222-
inline void startConversion() const { ADC->SWTRIG.bit.START = 1;}
222+
inline void startConversion() const {
223+
#ifdef FAMILY_SAMD5X
224+
ADC0->SWTRIG.bit.START = 1;
225+
#else
226+
ADC->SWTRIG.bit.START = 1;
227+
#endif
228+
}
223229
static void dmaDoneCallback(Adafruit_ZeroDMA *dma);
224230

225231
ChannelADC *queue_[kResultContainerSize]{};

0 commit comments

Comments
 (0)