1 //*****************************************************************************
2 //
3 //! @file am_hal_adc.c
4 //!
5 //! @brief Functions for interfacing with the Analog to Digital Converter.
6 //!
7 //! @addtogroup adc4_4p ADC - Analog-to-Digital Converter
8 //! @ingroup apollo4p_hal
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2023, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include "am_mcu_apollo.h"
51
52 //*****************************************************************************
53 //
54 // Private Types.
55 //
56 //*****************************************************************************
57 #define AM_HAL_MAGIC_ADC 0xAFAFAF
58 #define AM_HAL_ADC_CHK_HANDLE(h) ((h) && ((am_hal_handle_prefix_t *)(h))->s.bInit && (((am_hal_handle_prefix_t *)(h))->s.magic == AM_HAL_MAGIC_ADC))
59
60 #define ADC_CRITICAL_BEGIN(ui32Module) \
61 if ( 1 ) \
62 { \
63 uint32_t ui32adcintensave, ui32adcintstatsave; \
64 ui32adcintensave = ADCn(ui32Module)->INTEN; \
65 ADCn(ui32Module)->INTEN = 0x0; \
66 ui32adcintstatsave = ADCn(ui32Module)->INTSTAT; \
67
68 #define ADC_CRITICAL_END(ui32Module) \
69 if ( !(ui32adcintstatsave & (ADC_INTCLR_SCNCMP_Msk | \
70 ADC_INTCLR_CNVCMP_Msk))) \
71 { \
72 ADCn(ui32Module)->INTCLR = ADC_INTCLR_SCNCMP_Msk | \
73 ADC_INTCLR_CNVCMP_Msk; \
74 } \
75 ADCn(ui32Module)->INTEN = ui32adcintensave; \
76 }
77
78 //*****************************************************************************
79 //
80 //! @name Calibration Coefficients
81 //! @{
82 //! Default coefficients (used when trims not provided):
83 //! TEMP_DEFAULT = Temperature in deg K (e.g. 299.5 - 273.15 = 26.35)
84 //! AMBIENT_DEFAULT = Voltage measurement at default temperature.
85 //! OFFSET_DEFAULT = Default ADC offset at 1v.
86 //
87 //*****************************************************************************
88 #define AM_HAL_ADC_CALIB_TEMP_DEFAULT (299.5F)
89 #define AM_HAL_ADC_CALIB_AMBIENT_DEFAULT (1.02809F)
90 #define AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT (-0.004281F)
91 //! @}
92
93 // ****************************************************************************
94 //
95 // State
96 //
97 // ****************************************************************************
98 // ****************************************************************************
99 //
100 // Storage for pre-computed constant terms in the temperature sensor equation.
101 //
102 // ****************************************************************************
103 static float g_fTempEqnTerms = 0.0F;
104
105 // ****************************************************************************
106 //
107 //! @brief ADC Power save register state.
108 //
109 // ****************************************************************************
110 typedef struct
111 {
112 bool bValid;
113 uint32_t regCFG;
114 uint32_t regSL0CFG;
115 uint32_t regSL1CFG;
116 uint32_t regSL2CFG;
117 uint32_t regSL3CFG;
118 uint32_t regSL4CFG;
119 uint32_t regSL5CFG;
120 uint32_t regSL6CFG;
121 uint32_t regSL7CFG;
122 uint32_t regIntTrigTmr;
123 uint32_t regWULIM;
124 uint32_t regWLLIM;
125 uint32_t regINTEN;
126 } am_hal_adc_register_state_t;
127
128 // ****************************************************************************
129 //
130 //! @brief ADC State structure.
131 //
132 // ****************************************************************************
133 typedef struct
134 {
135 //
136 //! Handle validation prefix.
137 //
138 am_hal_handle_prefix_t prefix;
139
140 //
141 //! Physical module number.
142 //
143 uint32_t ui32Module;
144
145 //
146 //! ADC Capabilities.
147 //
148 am_hal_adc_capabilities_t capabilities;
149
150 //
151 //! Power Save-Restore register state
152 //
153 am_hal_adc_register_state_t registerState;
154
155 } am_hal_adc_state_t;
156
157 //*****************************************************************************
158 //
159 //! @brief Private SRAM view of temperature trims.
160 //!
161 //! This static SRAM union is private to the ADC HAL functions.
162 //
163 //*****************************************************************************
164 static union
165 {
166 //! These trim values are loaded as uint32_t values.
167 struct
168 {
169 //! Temperature of the package test head (in degrees Kelvin)
170 uint32_t ui32CalibrationTemperature;
171
172 //! Voltage corresponding to temperature measured on test head.
173 uint32_t ui32CalibrationVoltage;
174
175 //! ADC offset voltage measured on the package test head.
176 uint32_t ui32CalibrationOffset;
177
178 //! Flag if default (guess) or measured.
179 bool bMeasured;
180 } ui32;
181 //! These trim values are accessed as floats when used in temp calculations.
182 struct
183 {
184 //! Temperature of the package test head in degrees Kelvin
185 float fCalibrationTemperature;
186
187 //! Voltage corresponding to temperature measured on test head.
188 float fCalibrationVoltage;
189
190 //! ADC offset voltage measured on the package test head.
191 //! This value is recorded in volts, although the value
192 //! itself is likely to be on the order of millivolts.
193 float fCalibrationOffset;
194
195 //! Flag if default (guess) or measured.
196 float fMeasuredFlag;
197 } flt;
198 } priv_temp_trims;
199
200 //*****************************************************************************
201 //
202 //! @brief Private SRAM view of correction trims.
203 //!
204 //! This static SRAM union is private to the ADC HAL functions.
205 //
206 //*****************************************************************************
207 static union
208 {
209 //
210 // Define access to the general ADC correction values.
211 //
212 // These correction values are loaded as uint32_t values.
213 struct
214 {
215 uint32_t ui32ADCoffset;
216 uint32_t ui32ADCgain;
217 uint32_t ui32Sample;
218 } ui32;
219 // These correction values are accessed as floats
220 struct
221 {
222 float fADCoffset;
223 float fADCgain;
224 float fSample;
225 } flt;
226 } priv_correction_trims;
227
228 //*****************************************************************************
229 //
230 // Global Variables.
231 //
232 //*****************************************************************************
233 am_hal_adc_state_t g_ADCState[AM_REG_ADC_NUM_MODULES];
234
235 uint32_t g_ADCSlotsConfigured;
236
237 bool g_bDoADCadjust = false;
238
239 //*****************************************************************************
240 //
241 //! @brief ForceFIFOpop()
242 //
243 // ERR090: ADC "No CNVCMP interrupt for first single scan"
244 // Please refer to the Apollo4 errata for further information.
245 //
246 //*****************************************************************************
247 static void
ForceFIFOpop(void * pHandle)248 ForceFIFOpop(void *pHandle)
249 {
250 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
251
252 //
253 // Make sure the ADC is properly configured and enabled.
254 //
255 if ( !((ADCn(ui32Module)->CFG_b.RPTEN == ADC_CFG_RPTEN_SINGLE_SCAN) &&
256 (ADCn(ui32Module)->CFG_b.ADCEN == ADC_CFG_ADCEN_EN)) &&
257 !((ADCn(ui32Module)->CFG_b.ADCEN == ADC_CFG_ADCEN_EN) &&
258 (ADCn(ui32Module)->CFG_b.RPTEN == ADC_CFG_RPTEN_REPEATING_SCAN) &&
259 (ADCn(ui32Module)->INTTRIGTIMER_b.TIMEREN == ADC_INTTRIGTIMER_TIMEREN_EN)) )
260 {
261 return;
262 }
263
264 //
265 // ERR090: After enable, a forced FIFO pop is required to make
266 // sure that the first sample actually emitted is valid.
267 //
268 while ( _FLD2VAL(ADC_FIFO_COUNT, ADCn(ui32Module)->FIFO) == 0 )
269 {
270 am_hal_adc_sw_trigger(pHandle);
271 am_hal_delay_us(30);
272 }
273
274 while ( _FLD2VAL(ADC_FIFO_COUNT, ADCn(ui32Module)->FIFO) )
275 {
276 ADCn(ui32Module)->FIFO = 0; // Pop the FIFO
277 }
278
279 } // ForceFIFOpop()
280
281 //*****************************************************************************
282 //
283 //! @brief ADC initialization function
284 //!
285 //! @param ui32Module - module instance.
286 //! @param ppHandle - returns the handle for the module instance.
287 //!
288 //! This function accepts a module instance, allocates the interface and then
289 //! returns a handle to be used by the remaining interface functions.
290 //!
291 //! @return status - generic or interface specific status.
292 //!
293 //! @note A return of AM_HAL_STATUS_SUCCESS does not infer that the
294 //! temperature calibrations are valid. The caller must check the bMeasured
295 //! structure element in order to determine that.
296 //
297 //*****************************************************************************
298 uint32_t
am_hal_adc_initialize(uint32_t ui32Module,void ** ppHandle)299 am_hal_adc_initialize(uint32_t ui32Module, void **ppHandle)
300 {
301 uint32_t ui32Ret;
302
303 #ifndef AM_HAL_DISABLE_API_VALIDATION
304 //
305 // Validate the module number
306 //
307 if ( ui32Module >= AM_REG_ADC_NUM_MODULES )
308 {
309 return AM_HAL_STATUS_OUT_OF_RANGE;
310 }
311
312 //
313 // Check for valid arguements.
314 //
315 if ( !ppHandle )
316 {
317 return AM_HAL_STATUS_INVALID_ARG;
318 }
319
320 //
321 // Check if the handle is unallocated.
322 //
323 if ( g_ADCState[ui32Module].prefix.s.bInit )
324 {
325 return AM_HAL_STATUS_INVALID_OPERATION;
326 }
327 #endif // AM_HAL_DISABLE_API_VALIDATION
328
329 //
330 // Initialize the handle.
331 //
332 g_ADCState[ui32Module].prefix.s.bInit = true;
333 g_ADCState[ui32Module].prefix.s.magic = AM_HAL_MAGIC_ADC;
334 g_ADCState[ui32Module].ui32Module = ui32Module;
335
336 //
337 // Initialize the number of slots configured.
338 //
339 g_ADCSlotsConfigured = 0;
340
341 //
342 // Return the handle.
343 //
344 *ppHandle = (void *)&g_ADCState[ui32Module];
345
346 //
347 // Before returning, read the temperature trims from INFO1,
348 // which are safely read using am_hal_mram_info_read().
349 //
350 ui32Ret = am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_ATE_O / 4, 1, // INFO1, word offset, read 1 word
351 &priv_temp_trims.ui32.ui32CalibrationTemperature);
352 ui32Ret |= am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_MEASURED_O / 4, 1,
353 &priv_temp_trims.ui32.ui32CalibrationVoltage);
354 ui32Ret |= am_hal_mram_info_read(1, AM_REG_INFO1_TEMP_CAL_ADC_OFFSET_O / 4, 1,
355 &priv_temp_trims.ui32.ui32CalibrationOffset);
356
357 if ( (priv_temp_trims.ui32.ui32CalibrationTemperature == 0xFFFFFFFF) ||
358 (priv_temp_trims.ui32.ui32CalibrationVoltage == 0xFFFFFFFF) ||
359 (priv_temp_trims.ui32.ui32CalibrationOffset == 0xFFFFFFFF) ||
360 (ui32Ret != 0) )
361 {
362 //
363 // Since the device has not been calibrated on the tester, we'll load
364 // default calibration values. These default values should result
365 // in worst-case temperature measurements of +-6 degress C.
366 //
367 priv_temp_trims.flt.fCalibrationTemperature = AM_HAL_ADC_CALIB_TEMP_DEFAULT;
368 priv_temp_trims.flt.fCalibrationVoltage = AM_HAL_ADC_CALIB_AMBIENT_DEFAULT;
369 priv_temp_trims.flt.fCalibrationOffset = AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT;
370 priv_temp_trims.ui32.bMeasured = false;
371 }
372 else
373 {
374 priv_temp_trims.ui32.bMeasured = true;
375 }
376
377 //
378 // Get and save the ADC gain/offset correction values. These are really only
379 // needed for rev B0 and B1, but they will also be useful on later revs.
380 // Note: Only applies to the general ADC, not for AUDADC.
381 //
382 // If the correction values are 0xFFFFFFFF then we must disable CALONPWRUP.
383 //
384 ui32Ret = am_hal_mram_info_read(1, AM_REG_INFO1_ADC_GAIN_ERR_O / 4, 1,
385 &priv_correction_trims.ui32.ui32ADCgain);
386 ui32Ret |= am_hal_mram_info_read(1, AM_REG_INFO1_ADC_OFFSET_ERR_O / 4, 1,
387 &priv_correction_trims.ui32.ui32ADCoffset);
388
389 //
390 // Disable CALONPWRUP so that corrections can be applied to samples.
391 //
392 MCUCTRL->ADCCAL_b.CALONPWRUP = MCUCTRL_ADCCAL_CALONPWRUP_DIS;
393
394 if ( (ui32Ret != 0) ||
395 (priv_correction_trims.ui32.ui32ADCgain == 0xFFFFFFFF) ||
396 (priv_correction_trims.ui32.ui32ADCoffset == 0xFFFFFFFF) )
397 {
398 g_bDoADCadjust = false;
399 }
400 else
401 {
402 g_bDoADCadjust = true;
403 }
404
405 //
406 // Return the status.
407 // Note - This does not infer that temperature calibrations are valid.
408 // The caller must check bMeasured to determine that.
409 //
410 return AM_HAL_STATUS_SUCCESS;
411
412 } // am_hal_adc_initialize()
413
414 //*****************************************************************************
415 //
416 //! @brief ADC deinitialization function
417 //!
418 //! @param pHandle - returns the handle for the module instance.
419 //!
420 //! This function accepts a handle to an instance and de-initializes the
421 //! interface.
422 //!
423 //! @return status - generic or interface specific status.
424 //
425 //*****************************************************************************
426 uint32_t
am_hal_adc_deinitialize(void * pHandle)427 am_hal_adc_deinitialize(void *pHandle)
428 {
429 uint32_t status = AM_HAL_STATUS_SUCCESS;
430 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
431
432 #ifndef AM_HAL_DISABLE_API_VALIDATION
433 //
434 // Check the handle.
435 //
436 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
437 {
438 return AM_HAL_STATUS_INVALID_HANDLE;
439 }
440 #endif // AM_HAL_DISABLE_API_VALIDATION
441
442 if ( pADCState->prefix.s.bEnable )
443 {
444 status = am_hal_adc_disable(pHandle);
445 }
446
447 pADCState->prefix.s.bInit = false;
448
449 //
450 // Return the status.
451 //
452 return status;
453
454 } // am_hal_adc_deinitialize()
455
456 //*****************************************************************************
457 //
458 //! @brief ADC configuration function
459 //!
460 //! @param pHandle - handle for the module instance.
461 //! @param psConfig - pointer to the configuration structure.
462 //!
463 //! This function configures the ADC for operation.
464 //!
465 //! @return status - generic or interface specific status.
466 //
467 //*****************************************************************************
468 uint32_t
am_hal_adc_configure(void * pHandle,am_hal_adc_config_t * psConfig)469 am_hal_adc_configure(void *pHandle,
470 am_hal_adc_config_t *psConfig)
471 {
472 uint32_t ui32Config;
473 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
474 uint32_t ui32Module = pADCState->ui32Module;
475
476 #ifndef AM_HAL_DISABLE_API_VALIDATION
477 //
478 // Check the handle.
479 //
480 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
481 {
482 return AM_HAL_STATUS_INVALID_HANDLE;
483 }
484 #endif // AM_HAL_DISABLE_API_VALIDATION
485
486 ui32Config = 0;
487
488 //
489 // Set the ADC clock source.
490 //
491 if ( psConfig->eClock != AM_HAL_ADC_CLKSEL_HFRC_24MHZ )
492 {
493 return AM_HAL_STATUS_INVALID_ARG;
494 }
495
496 ui32Config |= _VAL2FLD(ADC_CFG_CLKSEL, psConfig->eClock);
497
498 //
499 // Set the ADC periodic trigger source.
500 //
501 ui32Config |= _VAL2FLD(ADC_CFG_RPTTRIGSEL, psConfig->eRepeatTrigger);
502
503 //
504 // Set the ADC trigger polarity.
505 //
506 ui32Config |= _VAL2FLD(ADC_CFG_TRIGPOL, psConfig->ePolarity);
507
508 //
509 // Set the ADC trigger.
510 //
511 ui32Config |= _VAL2FLD(ADC_CFG_TRIGSEL, psConfig->eTrigger);
512
513 //
514 // Set the Destructive FIFO read.
515 //
516 ui32Config |= _VAL2FLD(ADC_CFG_DFIFORDEN, 1);
517
518 //
519 // Set the ADC clock mode.
520 //
521 ui32Config |= _VAL2FLD(ADC_CFG_CKMODE, psConfig->eClockMode);
522
523 //
524 // Set the ADC low power mode.
525 //
526 ui32Config |= _VAL2FLD(ADC_CFG_LPMODE, psConfig->ePowerMode);
527
528 //
529 // Set the ADC repetition mode.
530 //
531 ui32Config |= _VAL2FLD(ADC_CFG_RPTEN, psConfig->eRepeat);
532
533 //
534 // Set the configuration in the ADC peripheral.
535 //
536 ADCn(ui32Module)->CFG = ui32Config;
537
538 //
539 // Return status.
540 //
541 return AM_HAL_STATUS_SUCCESS;
542
543 } // am_hal_adc_configure()
544
545 //*****************************************************************************
546 //
547 //! @brief ADC slot configuration function
548 //!
549 //! @param pHandle - handle for the module instance.
550 //! @param ui32SlotNumber - ADC Slot Number
551 //! @param pSlotConfig - pointer to the configuration structure.
552 //!
553 //! This function configures the ADC slot for operation.
554 //!
555 //! @return status - generic or interface specific status.
556 //
557 //*****************************************************************************
558 uint32_t
am_hal_adc_configure_slot(void * pHandle,uint32_t ui32SlotNumber,am_hal_adc_slot_config_t * pSlotConfig)559 am_hal_adc_configure_slot(void *pHandle,
560 uint32_t ui32SlotNumber,
561 am_hal_adc_slot_config_t *pSlotConfig)
562 {
563 uint32_t ui32Config;
564 uint32_t ui32RegOffset;
565 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
566 uint32_t ui32Module = pADCState->ui32Module;
567
568 #ifndef AM_HAL_DISABLE_API_VALIDATION
569 //
570 // Check the handle.
571 //
572 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
573 {
574 return AM_HAL_STATUS_INVALID_HANDLE;
575 }
576
577 //
578 // Check the slot number.
579 //
580 if ( ui32SlotNumber >= AM_HAL_ADC_MAX_SLOTS )
581 {
582 return AM_HAL_STATUS_OUT_OF_RANGE;
583 }
584
585 if ( (pSlotConfig->ui32TrkCyc < AM_HAL_ADC_MIN_TRKCYC) ||
586 (pSlotConfig->ui32TrkCyc > _FLD2VAL(ADC_SL0CFG_TRKCYC0, 0xFFFFFFFF)) )
587 {
588 return AM_HAL_STATUS_INVALID_ARG;
589 }
590 #endif // AM_HAL_DISABLE_API_VALIDATION
591
592 ui32Config = 0;
593
594 //
595 // Set the measurements to average
596 //
597 ui32Config |= _VAL2FLD(ADC_SL0CFG_ADSEL0, pSlotConfig->eMeasToAvg);
598
599 //
600 // Set additional sampling ADC clock cycles
601 //
602 ui32Config |= _VAL2FLD(ADC_SL0CFG_TRKCYC0, pSlotConfig->ui32TrkCyc);
603
604 //
605 // Set the precision mode.
606 //
607 ui32Config |= _VAL2FLD(ADC_SL0CFG_PRMODE0, pSlotConfig->ePrecisionMode);
608
609 //
610 // Set the channel.
611 //
612 ui32Config |= _VAL2FLD(ADC_SL0CFG_CHSEL0, pSlotConfig->eChannel);
613
614 //
615 // Enable window comparison if configured.
616 //
617 ui32Config |= _VAL2FLD(ADC_SL0CFG_WCEN0, pSlotConfig->bWindowCompare);
618
619 //
620 // Enable the slot if configured.
621 //
622 ui32Config |= _VAL2FLD(ADC_SL0CFG_SLEN0, pSlotConfig->bEnabled);
623
624 //
625 // Locate the correct register for this ADC slot.
626 //
627 ui32RegOffset = ((uint32_t)&ADCn(ui32Module)->SL0CFG) + (4 * ui32SlotNumber);
628
629 //
630 // Write the register with the caller's configuration value.
631 //
632 AM_REGVAL(ui32RegOffset) = ui32Config;
633
634 //
635 // Update the nubmer of slots configured.
636 //
637 g_ADCSlotsConfigured++;
638
639 //
640 // Return the status.
641 //
642 return AM_HAL_STATUS_SUCCESS;
643
644 } // am_hal_adc_configure_slot()
645
646 //*****************************************************************************
647 //
648 //! @brief ADC internal repeat trigger timer configuration function
649 //!
650 //! @param pHandle - handle for the module instance.
651 //! @param pConfig - pointer to the configuration structure.
652 //!
653 //! This function configures the ADC internal repeat trigger timer for operation.
654 //!
655 //! @return status - generic or interface specific status.
656 //
657 //*****************************************************************************
658 uint32_t
am_hal_adc_configure_irtt(void * pHandle,am_hal_adc_irtt_config_t * pConfig)659 am_hal_adc_configure_irtt(void *pHandle,
660 am_hal_adc_irtt_config_t *pConfig)
661 {
662 uint32_t ui32Config = 0;
663 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
664
665 #ifndef AM_HAL_DISABLE_API_VALIDATION
666 //
667 // Check the handle.
668 //
669 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
670 {
671 return AM_HAL_STATUS_INVALID_HANDLE;
672 }
673 #endif // AM_HAL_DISABLE_API_VALIDATION
674
675 //
676 // Disable ADC internal repeating trigger timer
677 //
678 ui32Config |= _VAL2FLD(ADC_INTTRIGTIMER_TIMEREN, ADC_INTTRIGTIMER_TIMEREN_DIS);
679
680 //
681 // Set ADC internal repeating trigger timer clock division
682 //
683 ui32Config |= _VAL2FLD(ADC_INTTRIGTIMER_CLKDIV, pConfig->eClkDiv);
684
685 //
686 // Set ADC internal repeating trigger timer count
687 //
688 ui32Config |= _VAL2FLD(ADC_INTTRIGTIMER_TIMERMAX, pConfig->ui32IrttCountMax);
689
690 //
691 // Set ADC internal repeating trigger timer configuration.
692 //
693 ADCn(ui32Module)->INTTRIGTIMER = ui32Config;
694
695 //
696 // Return the status.
697 //
698 return AM_HAL_STATUS_SUCCESS;
699
700 } // am_hal_adc_configure_irtt()
701
702 //*****************************************************************************
703 //
704 //! @brief ADC internal repeating trigger timer enable function
705 //!
706 //! @param pHandle - handle for the module instance.
707 //!
708 //! This function enables internal repeating trigger timer.
709 //!
710 //! @note - am_hal_adc_enable() must be called before this function.
711 //!
712 //! @return status - generic or interface specific status.
713 //
714 //*****************************************************************************
715 uint32_t
am_hal_adc_irtt_enable(void * pHandle)716 am_hal_adc_irtt_enable(void *pHandle)
717 {
718 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
719 uint32_t ui32Module = pADCState->ui32Module;
720
721 #ifndef AM_HAL_DISABLE_API_VALIDATION
722 //
723 // Check the handle.
724 //
725 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
726 {
727 return AM_HAL_STATUS_INVALID_HANDLE;
728 }
729
730 //
731 // Make sure the ADC has been enabled.
732 //
733 if ( ADCn(ui32Module)->CFG_b.ADCEN != ADC_CFG_ADCEN_EN )
734 {
735 return AM_HAL_STATUS_INVALID_OPERATION;
736 }
737 #endif // AM_HAL_DISABLE_API_VALIDATION
738
739 //
740 // Enable the ADC.
741 //
742 ADC_CRITICAL_BEGIN(ui32Module)
743 ADCn(ui32Module)->INTTRIGTIMER_b.TIMEREN = ADC_INTTRIGTIMER_TIMEREN_EN;
744 ForceFIFOpop(pHandle); // See errata ERR090
745 ADC_CRITICAL_END(ui32Module)
746
747 //
748 // Return the status.
749 //
750 return AM_HAL_STATUS_SUCCESS;
751
752 } // am_hal_adc_irtt_enable()
753
754 //*****************************************************************************
755 //
756 //! @brief ADC internal repeating trigger timer disable function
757 //!
758 //! @param pHandle - handle for the module instance.
759 //!
760 //! This function disables internal repeating trigger timer.
761 //!
762 //! @return status - generic or interface specific status.
763 //
764 //*****************************************************************************
765 uint32_t
am_hal_adc_irtt_disable(void * pHandle)766 am_hal_adc_irtt_disable(void *pHandle)
767 {
768 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
769 uint32_t ui32Module = pADCState->ui32Module;
770
771 #ifndef AM_HAL_DISABLE_API_VALIDATION
772 //
773 // Check the handle.
774 //
775 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
776 {
777 return AM_HAL_STATUS_INVALID_HANDLE;
778 }
779 #endif // AM_HAL_DISABLE_API_VALIDATION
780
781 //
782 // Enable the ADC.
783 //
784 ADCn(ui32Module)->INTTRIGTIMER_b.TIMEREN = ADC_INTTRIGTIMER_TIMEREN_DIS;
785
786 //
787 // Return the status.
788 //
789 return AM_HAL_STATUS_SUCCESS;
790
791 } // am_hal_adc_irtt_disable()
792
793 //*****************************************************************************
794 //
795 //! @brief ADC DMA configuration function
796 //!
797 //! @param pHandle - handle for the module instance.
798 //! @param pDMAConfig - pointer to the configuration structure.
799 //!
800 //! This function configures the ADC DMA for operation.
801 //!
802 //! @return status - generic or interface specific status.
803 //
804 //*****************************************************************************
805 uint32_t
am_hal_adc_configure_dma(void * pHandle,am_hal_adc_dma_config_t * pDMAConfig)806 am_hal_adc_configure_dma(void *pHandle,
807 am_hal_adc_dma_config_t *pDMAConfig)
808 {
809 uint32_t ui32Config;
810 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
811
812 #ifndef AM_HAL_DISABLE_API_VALIDATION
813 //
814 // Check the handle.
815 //
816 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
817 {
818 return AM_HAL_STATUS_INVALID_HANDLE;
819 }
820 #endif // AM_HAL_DISABLE_API_VALIDATION
821
822 ui32Config = 0;
823
824 //
825 // Configure the DMA complete power-off.
826 //
827 ui32Config |= _VAL2FLD(ADC_DMACFG_DPWROFF, 0); // DPWROFF not supported!
828
829 //
830 // Configure the data to be transferred.
831 //
832 if ( g_ADCSlotsConfigured > 1 )
833 {
834 // Need slot number to distinguish between slot results.
835 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_DIS);
836 }
837 else
838 {
839 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_EN);
840 }
841
842 //
843 // Enable DMA Halt on Status (DMAERR or DMACPL) by default. This bit is reserved in apollo4
844 //
845 // ui32Config |= _VAL2FLD(ADC_DMACFG_DMAHONSTAT, ADC_DMACFG_DMAHONSTAT_EN);
846
847 //
848 // Configure the DMA dynamic priority handling.
849 //
850 ui32Config |= _VAL2FLD(ADC_DMACFG_DMADYNPRI, pDMAConfig->bDynamicPriority);
851
852 //
853 // Configure the DMA static priority.
854 //
855 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAPRI, pDMAConfig->ePriority);
856
857 //
858 // Enable the DMA (does not start until ADC is enabled and triggered).
859 //
860 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAEN, ADC_DMACFG_DMAEN_EN);
861
862 //
863 // Set the DMA configuration.
864 //
865 ADCn(ui32Module)->DMACFG = ui32Config;
866
867 //
868 // Set the DMA transfer count.
869 //
870 ADCn(ui32Module)->DMATOTCOUNT_b.TOTCOUNT = pDMAConfig->ui32SampleCount;
871
872 //
873 // Set the DMA target address.
874 //
875 ADCn(ui32Module)->DMATARGADDR = pDMAConfig->ui32TargetAddress;
876
877 //
878 // Set the DMA trigger on FIFO 75% full.
879 //
880 ADCn(ui32Module)->DMATRIGEN = ADC_DMATRIGEN_DFIFO75_Msk;
881
882 //
883 // Return the status.
884 //
885 return AM_HAL_STATUS_SUCCESS;
886
887 } // am_hal_adc_configure_dma()
888
889 //*****************************************************************************
890 //
891 // ADC device specific control function.
892 //
893 //*****************************************************************************
894 uint32_t
am_hal_adc_control(void * pHandle,am_hal_adc_request_e eRequest,void * pArgs)895 am_hal_adc_control(void *pHandle,
896 am_hal_adc_request_e eRequest,
897 void *pArgs)
898 {
899 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
900
901 #ifndef AM_HAL_DISABLE_API_VALIDATION
902 //
903 // Check the handle.
904 //
905 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
906 {
907 return AM_HAL_STATUS_INVALID_HANDLE;
908 }
909 #endif // AM_HAL_DISABLE_API_VALIDATION
910
911 switch ( eRequest )
912 {
913 case AM_HAL_ADC_REQ_WINDOW_CONFIG:
914 {
915 am_hal_adc_window_config_t *pWindowConfig = (am_hal_adc_window_config_t *)pArgs;
916
917 #ifndef AM_HAL_DISABLE_API_VALIDATION
918 //
919 // Check the window limits.
920 //
921 if ( (pWindowConfig->ui32Upper > ADC_WULIM_ULIM_Msk) ||
922 (pWindowConfig->ui32Lower > ADC_WLLIM_LLIM_Msk) )
923 {
924 return AM_HAL_STATUS_OUT_OF_RANGE;
925 }
926 #endif // AM_HAL_DISABLE_API_VALIDATION
927 //
928 // Set the window comparison upper and lower limits.
929 //
930 ADCn(ui32Module)->WULIM = _VAL2FLD(ADC_WULIM_ULIM, pWindowConfig->ui32Upper);
931 ADCn(ui32Module)->WLLIM = _VAL2FLD(ADC_WLLIM_LLIM, pWindowConfig->ui32Lower);
932
933 //
934 // Set the window scale per precision mode if indicated.
935 //
936 ADCn(ui32Module)->SCWLIM = _VAL2FLD(ADC_SCWLIM_SCWLIMEN,
937 pWindowConfig->bScaleLimits);
938 }
939 break;
940
941 case AM_HAL_ADC_REQ_TEMP_CELSIUS_GET:
942 //
943 // pArgs must point to an array of 3 floats. To assure that the
944 // array is valid, upon calling the 3rd float (pArgs[2]) must be
945 // set to the value -123.456F.
946 //
947 if ( pArgs != NULL )
948 {
949 float *pfArray = (float*)pArgs;
950 float fTemp, fCalibration_temp, fCalibration_voltage, fCalibration_offset, fVoltage;
951
952 if ( pfArray[2] == -123.456F )
953 {
954 //
955 // The caller has provided a voltage as determined from the
956 // sample. The sample is scaled up by the reference voltage
957 // used on the device and then scaled down by the number of
958 // sample bits.
959 // i.e. scaled by AM_HAL_ADC_VREF / (1 << number_bits).
960 //
961 // Get the scaled voltage obtained from the ADC sample.
962 //
963 fVoltage = pfArray[0];
964
965 //
966 // Compute the calibrated temperature via the equation:
967 // T = m * Vmeas + T1 - m(V1 + Voff)
968 // m = AM_HAL_ADC_TEMPSENSOR_SLOPE (degK / V)
969 // Vmeas = The measured voltage (as based on the ADC code)
970 // T1 = Calibration temperature
971 // V1 = Calibration voltage (stored in volts)
972 // Voff = Calibration offset (stored in volts)
973 //
974 fCalibration_temp = priv_temp_trims.flt.fCalibrationTemperature;
975 fCalibration_voltage = priv_temp_trims.flt.fCalibrationVoltage;
976 fCalibration_offset = priv_temp_trims.flt.fCalibrationOffset;
977
978 //
979 // Compute the temperature in K
980 //
981 if ( g_fTempEqnTerms == 0.0F )
982 {
983 //
984 // The 2nd and 3rd terms of the temperature equation are
985 // consistent for a given device, so compute them only
986 // the first time and save.
987 //
988 g_fTempEqnTerms = -1.0F * AM_HAL_ADC_TEMPSENSOR_SLOPE;
989 g_fTempEqnTerms *= (fCalibration_voltage + fCalibration_offset);
990 g_fTempEqnTerms += fCalibration_temp;
991 }
992
993 //
994 // Determine the temperature in K by factoring
995 // in the supplied sample voltage
996 //
997 fTemp = AM_HAL_ADC_TEMPSENSOR_SLOPE * fVoltage;
998 fTemp += g_fTempEqnTerms;
999
1000 //
1001 // Give it back to the caller in Celsius.
1002 //
1003 pfArray[1] = fTemp - 273.15f;
1004 }
1005 else
1006 {
1007 return AM_HAL_STATUS_INVALID_OPERATION;
1008 }
1009 }
1010 else
1011 {
1012 return AM_HAL_STATUS_INVALID_ARG;
1013 }
1014 break;
1015
1016 case AM_HAL_ADC_REQ_TEMP_TRIMS_GET:
1017 //
1018 // pArgs must point to an array of 4 floats. To assure that the
1019 // array is valid, upon calling the 4th float (pArgs[3]) must be
1020 // set to the value -123.456.
1021 // On return, pArgs[3] is set to 1 if the returned values are
1022 // calibrated, or 0 if default calibration values.
1023 //
1024 if ( pArgs != NULL )
1025 {
1026 float *pfArray = (float*)pArgs;
1027 if ( pfArray[3] == -123.456F )
1028 {
1029 //
1030 // Return trim temperature as a float.
1031 //
1032 pfArray[0] = priv_temp_trims.flt.fCalibrationTemperature;
1033
1034 //
1035 // Return trim voltage as a float.
1036 //
1037 pfArray[1] = priv_temp_trims.flt.fCalibrationVoltage;
1038
1039 //
1040 // Return trim ADC offset voltage (in volts) as a float.
1041 //
1042 pfArray[2] = priv_temp_trims.flt.fCalibrationOffset;
1043
1044 //
1045 // Set the calibrated or uncalibrated flag
1046 //
1047 *(uint32_t*)&pfArray[3] = priv_temp_trims.ui32.bMeasured;
1048 }
1049 else
1050 {
1051 return AM_HAL_STATUS_INVALID_OPERATION;
1052 }
1053 }
1054 else
1055 {
1056 return AM_HAL_STATUS_INVALID_ARG;
1057 }
1058 break;
1059
1060 case AM_HAL_ADC_REQ_CORRECTION_TRIMS_GET:
1061 //
1062 // pArgs must point to an array of 4 floats. To assure that the
1063 // array is valid, upon calling the 4th float (pArgs[3]) must be
1064 // set to the value -123.456.
1065 //
1066 // On return,
1067 // pArgs[0] contains the offset that is applied to each sample.
1068 // pArgs[1] contains the gain that is applied to each sample.
1069 //
1070 // Note that the am_hal_adc_samples_read() automatically applies
1071 // the correction to samples. Therefore this function is primarily
1072 // supplied to the user for informational purposes only.
1073 //
1074 if ( pArgs != NULL )
1075 {
1076 float *pfArray = (float*)pArgs;
1077 if ( pfArray[3] == -123.456F )
1078 {
1079 //
1080 // Return ADC correction offset as a float.
1081 //
1082 pfArray[0] = priv_correction_trims.flt.fADCoffset;
1083
1084 //
1085 // Return ADC correction gain as a float.
1086 //
1087 pfArray[1] = priv_correction_trims.flt.fADCgain;
1088
1089 //
1090 // Set the return values.
1091 //
1092 ((uint32_t*)pArgs)[2] = 0;
1093 ((uint32_t*)pArgs)[3] = 0;
1094 }
1095 else
1096 {
1097 return AM_HAL_STATUS_INVALID_OPERATION;
1098 }
1099 }
1100 else
1101 {
1102 return AM_HAL_STATUS_INVALID_ARG;
1103 }
1104 break;
1105
1106 default:
1107 return AM_HAL_STATUS_INVALID_ARG;
1108 }
1109
1110 //
1111 // Return status.
1112 //
1113 return AM_HAL_STATUS_SUCCESS;
1114
1115 } // am_hal_adc_control()
1116
1117 //*****************************************************************************
1118 //
1119 //! @brief ADC enable function
1120 //!
1121 //! @param pHandle - handle for the module instance.
1122 //!
1123 //! This function enables the ADC operation.
1124 //!
1125 //! @return status - generic or interface specific status.
1126 //
1127 //*****************************************************************************
1128 uint32_t
am_hal_adc_enable(void * pHandle)1129 am_hal_adc_enable(void *pHandle)
1130 {
1131 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
1132 uint32_t ui32Module = pADCState->ui32Module;
1133
1134 #ifndef AM_HAL_DISABLE_API_VALIDATION
1135 //
1136 // Check the handle.
1137 //
1138 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1139 {
1140 return AM_HAL_STATUS_INVALID_HANDLE;
1141 }
1142
1143 if ( pADCState->prefix.s.bEnable )
1144 {
1145 return AM_HAL_STATUS_SUCCESS;
1146 }
1147 #endif // AM_HAL_DISABLE_API_VALIDATION
1148
1149 //
1150 // Enable the ADC.
1151 //
1152 ADC_CRITICAL_BEGIN(ui32Module)
1153 ADCn(ui32Module)->CFG_b.ADCEN = ADC_CFG_ADCEN_EN;
1154
1155 //
1156 // Set flag to indicate module is enabled.
1157 //
1158 pADCState->prefix.s.bEnable = true;
1159 ForceFIFOpop(pHandle); // See errata ERR090
1160 ADC_CRITICAL_END(ui32Module)
1161
1162 //
1163 // Return the status.
1164 //
1165 return AM_HAL_STATUS_SUCCESS;
1166
1167 } // am_hal_adc_enable()
1168
1169 //*****************************************************************************
1170 //
1171 //! @brief ADC disable function
1172 //!
1173 //! @param pHandle - handle for the module instance.
1174 //!
1175 //! This function disables the ADC operation.
1176 //!
1177 //! @return status - generic or interface specific status.
1178 //
1179 //*****************************************************************************
1180 uint32_t
am_hal_adc_disable(void * pHandle)1181 am_hal_adc_disable(void *pHandle)
1182 {
1183 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
1184 uint32_t ui32Module = pADCState->ui32Module;
1185
1186 #ifndef AM_HAL_DISABLE_API_VALIDATION
1187 //
1188 // Check the handle.
1189 //
1190 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1191 {
1192 return AM_HAL_STATUS_INVALID_HANDLE;
1193 }
1194 #endif // AM_HAL_DISABLE_API_VALIDATION
1195
1196 //
1197 // Before disabling the ADC, clear RPTEN per the register description, "When
1198 // disabling the ADC (setting ADCEN to '0') the RPTEN bit should be cleared."
1199 //
1200 ADCn(ui32Module)->CFG_b.RPTEN = ADC_CFG_RPTEN_SINGLE_SCAN;
1201
1202 //
1203 // Disable the ADC.
1204 //
1205 ADCn(ui32Module)->CFG_b.ADCEN = ADC_CFG_ADCEN_DIS;
1206
1207 //
1208 // Set flag to indicate module is disabled.
1209 //
1210 pADCState->prefix.s.bEnable = false;
1211
1212 //
1213 // Return the status.
1214 //
1215 return AM_HAL_STATUS_SUCCESS;
1216
1217 } // am_hal_adc_disable()
1218
1219 //*****************************************************************************
1220 //
1221 //! @brief ADC status function
1222 //!
1223 //! @param pHandle - handle for the interface.
1224 //! @param pStatus - return status for the interface
1225 //!
1226 //! This function returns the current status of the DMA operation.
1227 //!
1228 //! @return status - DMA status flags.
1229 //
1230 //*****************************************************************************
1231 uint32_t
am_hal_adc_status_get(void * pHandle,am_hal_adc_status_t * pStatus)1232 am_hal_adc_status_get(void *pHandle, am_hal_adc_status_t *pStatus )
1233 {
1234 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
1235
1236 #ifndef AM_HAL_DISABLE_API_VALIDATION
1237 //
1238 // Check the handle.
1239 //
1240 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1241 {
1242 return AM_HAL_STATUS_INVALID_HANDLE;
1243 }
1244 #endif // AM_HAL_DISABLE_API_VALIDATION
1245
1246 //
1247 // Get the power status.
1248 //
1249 pStatus->bPoweredOn = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
1250 _VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_ON);
1251
1252 //
1253 // Get the low power mode 1 status.
1254 //
1255 pStatus->bLPMode1 = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
1256 _VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_POWERED_DOWN);
1257
1258 //
1259 // Get the DMA status.
1260 //
1261 pStatus->bErr = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMAERR_Msk) > 0);
1262 pStatus->bCmp = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMACPL_Msk) > 0);
1263 pStatus->bTIP = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMATIP_Msk) > 0);
1264
1265 //
1266 // Return the status.
1267 //
1268 return AM_HAL_STATUS_SUCCESS;
1269
1270 } // am_hal_adc_status_get()
1271
1272 //*****************************************************************************
1273 //
1274 //! @brief ADC enable interrupts function
1275 //!
1276 //! @param pHandle - handle for the interface.
1277 //! @param ui32IntMask - ADC interrupt mask.
1278 //!
1279 //! This function enables the specific indicated interrupts.
1280 //!
1281 //! @return status - generic or interface specific status.
1282 //
1283 //*****************************************************************************
1284 uint32_t
am_hal_adc_interrupt_enable(void * pHandle,uint32_t ui32IntMask)1285 am_hal_adc_interrupt_enable(void *pHandle, uint32_t ui32IntMask)
1286 {
1287 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1288
1289 #ifndef AM_HAL_DISABLE_API_VALIDATION
1290 //
1291 // Check the handle.
1292 //
1293 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1294 {
1295 return AM_HAL_STATUS_INVALID_HANDLE;
1296 }
1297 #endif // AM_HAL_DISABLE_API_VALIDATION
1298
1299 //
1300 // Enable the interrupts.
1301 //
1302 ADCn(ui32Module)->INTEN |= ui32IntMask;
1303
1304 //
1305 // Return the status.
1306 //
1307 return AM_HAL_STATUS_SUCCESS;
1308
1309 } // am_hal_adc_interrupt_enable()
1310
1311 //*****************************************************************************
1312 //
1313 //! @brief ADC disable interrupts function
1314 //!
1315 //! @param pHandle - handle for the interface.
1316 //! @param ui32IntMask - ADC interrupt mask.
1317 //!
1318 //! This function disable the specific indicated interrupts.
1319 //!
1320 //! @return status - generic or interface specific status.
1321 //
1322 //*****************************************************************************
1323 uint32_t
am_hal_adc_interrupt_disable(void * pHandle,uint32_t ui32IntMask)1324 am_hal_adc_interrupt_disable(void *pHandle, uint32_t ui32IntMask)
1325 {
1326 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1327
1328 #ifndef AM_HAL_DISABLE_API_VALIDATION
1329 //
1330 // Check the handle.
1331 //
1332 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1333 {
1334 return AM_HAL_STATUS_INVALID_HANDLE;
1335 }
1336 #endif // AM_HAL_DISABLE_API_VALIDATION
1337
1338 //
1339 // Disable the interrupts.
1340 //
1341 ADCn(ui32Module)->INTEN &= ~ui32IntMask;
1342
1343 //
1344 // Return the status.
1345 //
1346 return AM_HAL_STATUS_SUCCESS;
1347
1348 } // am_hal_adc_interrupt_disable()
1349
1350 //*****************************************************************************
1351 //
1352 //! @brief ADC interrupt status function
1353 //!
1354 //! @param pHandle - handle for the interface.
1355 //! @param pui32Status - pointer to status
1356 //! @param bEnabledOnly - if ADC enabled
1357 //!
1358 //! This function returns the specific indicated interrupt status.
1359 //!
1360 //! @return status - generic or interface specific status.
1361 //
1362 //*****************************************************************************
1363 uint32_t
am_hal_adc_interrupt_status(void * pHandle,uint32_t * pui32Status,bool bEnabledOnly)1364 am_hal_adc_interrupt_status(void *pHandle,
1365 uint32_t *pui32Status,
1366 bool bEnabledOnly)
1367 {
1368 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1369
1370 #ifndef AM_HAL_DISABLE_API_VALIDATION
1371 //
1372 // Check the handle.
1373 //
1374 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1375 {
1376 return AM_HAL_STATUS_INVALID_HANDLE;
1377 }
1378 #endif // AM_HAL_DISABLE_API_VALIDATION
1379
1380 //
1381 // if requested, only return the interrupts that are enabled.
1382 //
1383 if ( bEnabledOnly )
1384 {
1385 uint32_t ui32RetVal = ADCn(ui32Module)->INTSTAT;
1386 *pui32Status = ADCn(ui32Module)->INTEN & ui32RetVal;
1387 }
1388 else
1389 {
1390 *pui32Status = ADCn(ui32Module)->INTSTAT;
1391 }
1392
1393 //
1394 // Return the status.
1395 //
1396 return AM_HAL_STATUS_SUCCESS;
1397
1398 } // am_hal_adc_interrupt_status()
1399
1400 //*****************************************************************************
1401 //
1402 //! @brief ADC interrupt clear
1403 //!
1404 //! @param pHandle - handle for the interface.
1405 //! @param ui32IntMask - uint32_t for interrupts to clear
1406 //!
1407 //! This function clears the interrupts for the given peripheral.
1408 //!
1409 //! @return status - generic or interface specific status.
1410 //
1411 //*****************************************************************************
1412 uint32_t
am_hal_adc_interrupt_clear(void * pHandle,uint32_t ui32IntMask)1413 am_hal_adc_interrupt_clear(void *pHandle, uint32_t ui32IntMask)
1414 {
1415 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1416
1417 #ifndef AM_HAL_DISABLE_API_VALIDATION
1418 //
1419 // Check the handle.
1420 //
1421 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1422 {
1423 return AM_HAL_STATUS_INVALID_HANDLE;
1424 }
1425 #endif // AM_HAL_DISABLE_API_VALIDATION
1426
1427 //
1428 // Clear the interrupts.
1429 //
1430 ADCn(ui32Module)->INTCLR = ui32IntMask;
1431
1432 //
1433 // Return the status.
1434 //
1435 return AM_HAL_STATUS_SUCCESS;
1436
1437 } // am_hal_adc_interrupt_clear()
1438
1439 //*****************************************************************************
1440 //
1441 // sample_correction_apply()
1442 //
1443 //*****************************************************************************
1444 static uint32_t
sample_correction_apply(uint32_t ui32Sample,bool bApplyCorrection)1445 sample_correction_apply(uint32_t ui32Sample, bool bApplyCorrection)
1446 {
1447 float fSampleAdj;
1448
1449 if ( g_bDoADCadjust )
1450 {
1451 //
1452 // Apply the gain/offset correction to the full sample for all
1453 // channels except temperature.
1454 //
1455 if ( bApplyCorrection )
1456 {
1457 //
1458 // General correction equation:
1459 // sample_corrected = (sample / (1.0F - gain)) - offset
1460 //
1461 fSampleAdj = (float)(AM_HAL_ADC_FIFO_SAMPLE(ui32Sample) * AM_HAL_ADC_VREFMV / AM_HAL_ADC_SAMPLE_DIVISOR);
1462 fSampleAdj /= (1.0F - priv_correction_trims.flt.fADCgain);
1463
1464 //
1465 // Convert the offset from volts to mv.
1466 //
1467 fSampleAdj -= (priv_correction_trims.flt.fADCoffset * 1000.0F);
1468 fSampleAdj = fSampleAdj * AM_HAL_ADC_SAMPLE_DIVISORF / AM_HAL_ADC_VREFMVF;
1469
1470 //
1471 // Check for overflow
1472 //
1473 if ( fSampleAdj > 4095.0F )
1474 {
1475 fSampleAdj = 4095.0F;
1476 }
1477
1478 ui32Sample &= 0xFFF00000;
1479 ui32Sample |= ((((uint32_t)fSampleAdj) << 6) & AM_HAL_ADC_SAMPLE_MASK_FULL);
1480 }
1481 }
1482 return ui32Sample;
1483 } // sample_correction_apply()
1484
1485 //*****************************************************************************
1486 //
1487 // ADC sample read function
1488 //
1489 // This function reads samples from the ADC FIFO or an SRAM sample buffer
1490 // returned by a DMA operation.
1491 //
1492 //*****************************************************************************
1493 uint32_t
am_hal_adc_samples_read(void * pHandle,bool bFullSample,uint32_t * pui32InSampleBuffer,uint32_t * pui32InOutNumberSamples,am_hal_adc_sample_t * pui32OutBuffer)1494 am_hal_adc_samples_read(void *pHandle,
1495 bool bFullSample,
1496 uint32_t *pui32InSampleBuffer,
1497 uint32_t *pui32InOutNumberSamples,
1498 am_hal_adc_sample_t *pui32OutBuffer)
1499 {
1500 uint32_t ui32Sample;
1501 uint32_t ui32RequestedSamples = *pui32InOutNumberSamples;
1502 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1503 uint32_t ui32slot, ui32slotcfgaddr, ui32chsel, ui32TempMask;
1504 bool bTempChnl;
1505
1506 #ifndef AM_HAL_DISABLE_API_VALIDATION
1507 //
1508 // Check the handle.
1509 //
1510 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1511 {
1512 return AM_HAL_STATUS_INVALID_HANDLE;
1513 }
1514
1515 //
1516 // Check the output sample buffer pointer.
1517 //
1518 if ( NULL == pui32OutBuffer )
1519 {
1520 return AM_HAL_STATUS_INVALID_ARG;
1521 }
1522 #endif // AM_HAL_DISABLE_API_VALIDATION
1523
1524 *pui32InOutNumberSamples = 0;
1525
1526 //
1527 // Check if we are reading directly from FIFO or DMA SRAM buffer.
1528 //
1529 if ( pui32InSampleBuffer == NULL )
1530 {
1531 //
1532 // Grab a value from the ADC FIFO
1533 //
1534 do
1535 {
1536 ui32Sample = ADCn(ui32Module)->FIFOPR;
1537
1538 ui32slot = AM_HAL_ADC_FIFO_SLOT(ui32Sample);
1539 ui32slotcfgaddr = ((uint32_t)(&ADCn(ui32Module)->SL0CFG)) + (4 * ui32slot);
1540 ui32chsel = _FLD2VAL(ADC_SL0CFG_CHSEL0, AM_REGVAL(ui32slotcfgaddr));
1541 bTempChnl = (ui32chsel == ADC_SL0CFG_CHSEL0_TEMP) ? true : false;
1542
1543 //
1544 // Apply the sample correction.
1545 //
1546 ui32Sample = sample_correction_apply(ui32Sample, !bTempChnl);
1547 pui32OutBuffer->ui32Slot = AM_HAL_ADC_FIFO_SLOT(ui32Sample);
1548 pui32OutBuffer->ui32Sample = bFullSample ?
1549 AM_HAL_ADC_FIFO_FULL_SAMPLE(ui32Sample) :
1550 AM_HAL_ADC_FIFO_SAMPLE(ui32Sample);
1551 pui32OutBuffer++;
1552 (*pui32InOutNumberSamples)++;
1553 } while ((AM_HAL_ADC_FIFO_COUNT(ui32Sample) > 0) &&
1554 (*pui32InOutNumberSamples < ui32RequestedSamples));
1555 }
1556 else
1557 {
1558 //
1559 // Before processing the buffer of samples, pre-process the slot
1560 // configuration registers to build a mask of slots that might be
1561 // configured as temperature. The mask will be used later for
1562 // determining whether to apply correction.
1563 // This, of course, depends on and assumes that the slots are still
1564 // configured as they were while the samples were taken.
1565 //
1566 ui32TempMask = 0;
1567 ui32TempMask |= (_FLD2VAL(ADC_SL0CFG_CHSEL0, ADC->SL0CFG) == ADC_SL0CFG_CHSEL0_TEMP) ? 1 << 0 : 0;
1568 ui32TempMask |= (_FLD2VAL(ADC_SL1CFG_CHSEL1, ADC->SL1CFG) == ADC_SL1CFG_CHSEL1_TEMP) ? 1 << 1 : 0;
1569 ui32TempMask |= (_FLD2VAL(ADC_SL2CFG_CHSEL2, ADC->SL2CFG) == ADC_SL2CFG_CHSEL2_TEMP) ? 1 << 2 : 0;
1570 ui32TempMask |= (_FLD2VAL(ADC_SL3CFG_CHSEL3, ADC->SL3CFG) == ADC_SL3CFG_CHSEL3_TEMP) ? 1 << 3 : 0;
1571 ui32TempMask |= (_FLD2VAL(ADC_SL4CFG_CHSEL4, ADC->SL4CFG) == ADC_SL4CFG_CHSEL4_TEMP) ? 1 << 4 : 0;
1572 ui32TempMask |= (_FLD2VAL(ADC_SL5CFG_CHSEL5, ADC->SL5CFG) == ADC_SL5CFG_CHSEL5_TEMP) ? 1 << 5 : 0;
1573 ui32TempMask |= (_FLD2VAL(ADC_SL6CFG_CHSEL6, ADC->SL6CFG) == ADC_SL6CFG_CHSEL6_TEMP) ? 1 << 6 : 0;
1574 ui32TempMask |= (_FLD2VAL(ADC_SL7CFG_CHSEL7, ADC->SL7CFG) == ADC_SL7CFG_CHSEL7_TEMP) ? 1 << 7 : 0;
1575
1576 //
1577 // Process the samples from the provided sample buffer
1578 //
1579 do
1580 {
1581 //
1582 // Apply the sample correction.
1583 // Note that the correction is not used for temperature.
1584 //
1585 ui32slot = AM_HAL_ADC_FIFO_SLOT(*pui32InSampleBuffer);
1586 ui32Sample = AM_HAL_ADC_FIFO_FULL_SAMPLE(*pui32InSampleBuffer);
1587 bTempChnl = ((ui32TempMask >> ui32slot) & 1) ? true : false;
1588 pui32OutBuffer->ui32Sample = AM_HAL_ADC_FIFO_SAMPLE(sample_correction_apply(ui32Sample,
1589 !bTempChnl));
1590 pui32OutBuffer->ui32Slot = ui32slot;
1591 pui32InSampleBuffer++;
1592 pui32OutBuffer++;
1593 (*pui32InOutNumberSamples)++;
1594 } while (*pui32InOutNumberSamples < ui32RequestedSamples);
1595 }
1596
1597 //
1598 // Return FIFO valid bits.
1599 //
1600 return AM_HAL_STATUS_SUCCESS;
1601
1602 } // am_hal_adc_samples_read()
1603
1604 //*****************************************************************************
1605 //
1606 //! @brief Issue Software Trigger to the ADC.
1607 //!
1608 //! @param pHandle - handle for the module instance.
1609 //!
1610 //! This function triggers the ADC operation.
1611 //!
1612 //! @return status - generic or interface specific status.
1613 //
1614 //*****************************************************************************
1615 uint32_t
am_hal_adc_sw_trigger(void * pHandle)1616 am_hal_adc_sw_trigger(void *pHandle)
1617 {
1618 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1619
1620 #ifndef AM_HAL_DISABLE_API_VALIDATION
1621 //
1622 // Check the handle.
1623 //
1624 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1625 {
1626 return AM_HAL_STATUS_INVALID_HANDLE;
1627 }
1628 #endif // AM_HAL_DISABLE_API_VALIDATION
1629
1630 //
1631 // Write to the Software trigger register in the ADC.
1632 //
1633 ADCn(ui32Module)->SWT = 0x37;
1634
1635 //
1636 // Return the status.
1637 //
1638 return AM_HAL_STATUS_SUCCESS;
1639
1640 } // am_hal_adc_sw_trigger()
1641
1642 //*****************************************************************************
1643 //
1644 //! @brief ADC power control function
1645 //!
1646 //! @param pHandle - handle for the interface.
1647 //! @param ePowerState - the desired power state to move the peripheral to.
1648 //! @param bRetainState - flag (if true) to save/restore peripheral state upon
1649 //! power state change.
1650 //!
1651 //! This function updates the peripheral to a given power state.
1652 //!
1653 //! @return status - generic or interface specific status.
1654 //
1655 //*****************************************************************************
1656 uint32_t
am_hal_adc_power_control(void * pHandle,am_hal_sysctrl_power_state_e ePowerState,bool bRetainState)1657 am_hal_adc_power_control(void *pHandle,
1658 am_hal_sysctrl_power_state_e ePowerState,
1659 bool bRetainState)
1660 {
1661 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
1662 uint32_t ui32Module = pADCState->ui32Module;
1663
1664 #ifndef AM_HAL_DISABLE_API_VALIDATION
1665 //
1666 // Check the handle.
1667 //
1668 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1669 {
1670 return AM_HAL_STATUS_INVALID_HANDLE;
1671 }
1672 #endif // AM_HAL_DISABLE_API_VALIDATION
1673
1674 //
1675 // Decode the requested power state and update ADC operation accordingly.
1676 //
1677 switch (ePowerState)
1678 {
1679 case AM_HAL_SYSCTRL_WAKE:
1680 if ( bRetainState && !pADCState->registerState.bValid )
1681 {
1682 return AM_HAL_STATUS_INVALID_OPERATION;
1683 }
1684
1685 //
1686 // Enable the ADC power domain.
1687 //
1688 am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_ADC);
1689
1690 if ( bRetainState )
1691 {
1692 ADCn(ui32Module)->SL0CFG = pADCState->registerState.regSL0CFG;
1693 ADCn(ui32Module)->SL1CFG = pADCState->registerState.regSL1CFG;
1694 ADCn(ui32Module)->SL2CFG = pADCState->registerState.regSL2CFG;
1695 ADCn(ui32Module)->SL3CFG = pADCState->registerState.regSL3CFG;
1696 ADCn(ui32Module)->SL4CFG = pADCState->registerState.regSL4CFG;
1697 ADCn(ui32Module)->SL5CFG = pADCState->registerState.regSL5CFG;
1698 ADCn(ui32Module)->SL6CFG = pADCState->registerState.regSL6CFG;
1699 ADCn(ui32Module)->SL7CFG = pADCState->registerState.regSL7CFG;
1700 ADCn(ui32Module)->INTTRIGTIMER = pADCState->registerState.regIntTrigTmr;
1701 ADCn(ui32Module)->WULIM = pADCState->registerState.regWULIM;
1702 ADCn(ui32Module)->WLLIM = pADCState->registerState.regWLLIM;
1703
1704 ADCn(ui32Module)->INTEN = 0x0;
1705 ADC_CRITICAL_BEGIN(ui32Module)
1706 ADCn(ui32Module)->CFG = pADCState->registerState.regCFG;
1707 ForceFIFOpop(pHandle); // See errata ERR090
1708 ADC_CRITICAL_END(ui32Module)
1709 ADCn(ui32Module)->INTEN = pADCState->registerState.regINTEN;
1710 pADCState->registerState.bValid = false;
1711 }
1712
1713 break;
1714
1715 case AM_HAL_SYSCTRL_NORMALSLEEP:
1716 case AM_HAL_SYSCTRL_DEEPSLEEP:
1717 if ( bRetainState )
1718 {
1719 pADCState->registerState.regSL0CFG = ADCn(ui32Module)->SL0CFG;
1720 pADCState->registerState.regSL1CFG = ADCn(ui32Module)->SL1CFG;
1721 pADCState->registerState.regSL2CFG = ADCn(ui32Module)->SL2CFG;
1722 pADCState->registerState.regSL3CFG = ADCn(ui32Module)->SL3CFG;
1723 pADCState->registerState.regSL4CFG = ADCn(ui32Module)->SL4CFG;
1724 pADCState->registerState.regSL5CFG = ADCn(ui32Module)->SL5CFG;
1725 pADCState->registerState.regSL6CFG = ADCn(ui32Module)->SL6CFG;
1726 pADCState->registerState.regSL7CFG = ADCn(ui32Module)->SL7CFG;
1727 pADCState->registerState.regIntTrigTmr = ADCn(ui32Module)->INTTRIGTIMER;
1728 pADCState->registerState.regWULIM = ADCn(ui32Module)->WULIM;
1729 pADCState->registerState.regWLLIM = ADCn(ui32Module)->WLLIM;
1730 pADCState->registerState.regINTEN = ADCn(ui32Module)->INTEN;
1731 pADCState->registerState.regCFG = ADCn(ui32Module)->CFG;
1732
1733 pADCState->registerState.bValid = true;
1734 }
1735
1736 //
1737 // Disable the ADC power domain.
1738 //
1739 am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);
1740 break;
1741
1742 default:
1743 return AM_HAL_STATUS_INVALID_ARG;
1744 }
1745
1746 //
1747 // Return the status.
1748 //
1749 return AM_HAL_STATUS_SUCCESS;
1750
1751 } // am_hal_adc_power_control()
1752
1753 //*****************************************************************************
1754 //
1755 // End Doxygen group.
1756 //! @}
1757 //
1758 //*****************************************************************************
1759