1 //*****************************************************************************
2 //
3 //! @file am_hal_adc.c
4 //!
5 //! @brief Functions for Interfacing with the Analog to Digital Converter.
6 //!
7 //! @addtogroup adc3 ADC - Analog-to-Digital Converter
8 //! @ingroup apollo3_hal
9 //! @{
10 //
11 //*****************************************************************************
12
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, 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_3_2_0-dd5f40c14b 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
58 #define AM_HAL_MAGIC_ADC 0xAFAFAF
59 #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))
60
61 // ****************************************************************************
62 //
63 //! Apollo3 Temperature Trim Value Locations and default coefficients.
64 //
65 // ****************************************************************************
66 #define AM_HAL_ADC_CALIB_TEMP_ADDR (0x50023840)
67 #define AM_HAL_ADC_CALIB_AMBIENT_ADDR (0x50023844)
68 #define AM_HAL_ADC_CALIB_ADC_OFFSET_ADDR (0x50023848)
69
70 // ****************************************************************************
71 //
72 //! Default coefficients (used when trims not provided):
73 //! TEMP_DEFAULT = Temperature in deg K (e.g. 299.5 - 273.15 = 26.35)
74 //! AMBIENT_DEFAULT = Voltage measurement at default temperature.
75 //! OFFSET_DEFAULT = Default ADC offset at 1v.
76 //
77 // ****************************************************************************
78 #define AM_HAL_ADC_CALIB_TEMP_DEFAULT (299.5F)
79 #define AM_HAL_ADC_CALIB_AMBIENT_DEFAULT (1.02809F)
80 #define AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT (-0.004281F)
81
82
83 //
84 //! ADC Power save register state.
85 //
86 typedef struct
87 {
88 bool bValid;
89 uint32_t regCFG;
90 uint32_t regSL0CFG;
91 uint32_t regSL1CFG;
92 uint32_t regSL2CFG;
93 uint32_t regSL3CFG;
94 uint32_t regSL4CFG;
95 uint32_t regSL5CFG;
96 uint32_t regSL6CFG;
97 uint32_t regSL7CFG;
98 uint32_t regWULIM;
99 uint32_t regWLLIM;
100 uint32_t regINTEN;
101 } am_hal_adc_register_state_t;
102
103 //
104 //! ADC State structure.
105 //
106 typedef struct
107 {
108 //
109 //! Handle validation prefix.
110 //
111 am_hal_handle_prefix_t prefix;
112
113 //
114 //! Physical module number.
115 //
116 uint32_t ui32Module;
117
118 //
119 //! ADC Capabilities.
120 //
121 am_hal_adc_capabilities_t capabilities;
122
123 //! Power Save-Restore register state
124 am_hal_adc_register_state_t registerState;
125
126 } am_hal_adc_state_t;
127
128 //*****************************************************************************
129 //
130 //! @brief Private SRAM view of temperature trims.
131 //!
132 //! This static SRAM union is private to the ADC HAL functions.
133 //
134 //*****************************************************************************
135 static union
136 {
137 //! These trim values are loaded as uint32_t values.
138 struct
139 {
140 //! Temperature of the package test head (in degrees Kelvin)
141 uint32_t ui32CalibrationTemperature;
142
143 //! Voltage corresponding to temperature measured on test head.
144 uint32_t ui32CalibrationVoltage;
145
146 //! ADC offset voltage measured on the package test head.
147 uint32_t ui32CalibrationOffset;
148
149 //! Flag if default (guess) or measured.
150 bool bMeasured;
151 } ui32;
152 //! These trim values are accessed as floats when used in temp calculations.
153 struct
154 {
155 //! Temperature of the package test head in degrees Kelvin
156 float fCalibrationTemperature;
157
158 //! Voltage corresponding to temperature measured on test head.
159 float fCalibrationVoltage;
160
161 //! ADC offset voltage measured on the package test head.
162 float fCalibrationOffset;
163
164 //! Flag if default (guess) or measured.
165 float fMeasuredFlag;
166 } flt;
167 } priv_temp_trims;
168
169 //*****************************************************************************
170 //
171 //! Global Variables.
172 //
173 //*****************************************************************************
174 am_hal_adc_state_t g_ADCState[AM_REG_ADC_NUM_MODULES];
175
176 uint32_t g_ADCSlotsConfigured;
177
178 //
179 //! Storage for pre-computed constant terms in the temperature sensor equation.
180 //
181 static float g_fTempEqnTerms = 0.0F;
182
183 //*****************************************************************************
184 //
185 // @brief ADC initialization function
186 //
187 // @param ui32Module - module instance.
188 // @param ppHandle - returns the handle for the module instance.
189 //
190 // This function accepts a module instance, allocates the interface and then
191 // returns a handle to be used by the remaining interface functions.
192 //
193 // @return status - generic or interface specific status.
194 //
195 //*****************************************************************************
196 uint32_t
am_hal_adc_initialize(uint32_t ui32Module,void ** ppHandle)197 am_hal_adc_initialize(uint32_t ui32Module, void **ppHandle)
198 {
199
200 #ifndef AM_HAL_DISABLE_API_VALIDATION
201 //
202 //! Validate the module number
203 //
204 if ( ui32Module >= AM_REG_ADC_NUM_MODULES )
205 {
206 return AM_HAL_STATUS_OUT_OF_RANGE;
207 }
208
209 //
210 //! Check for valid arguements.
211 //
212 if ( !ppHandle )
213 {
214 return AM_HAL_STATUS_INVALID_ARG;
215 }
216
217 //
218 //! Check if the handle is unallocated.
219 //
220 if ( g_ADCState[ui32Module].prefix.s.bInit )
221 {
222 return AM_HAL_STATUS_INVALID_OPERATION;
223 }
224 #endif // AM_HAL_DISABLE_API_VALIDATION
225
226 //
227 //! Initialize the handle.
228 //
229 g_ADCState[ui32Module].prefix.s.bInit = true;
230 g_ADCState[ui32Module].prefix.s.magic = AM_HAL_MAGIC_ADC;
231 g_ADCState[ui32Module].ui32Module = ui32Module;
232
233 //
234 //! Initialize the number of slots configured.
235 //
236 g_ADCSlotsConfigured = 0;
237
238 //
239 //! Return the handle.
240 //
241 *ppHandle = (void *)&g_ADCState[ui32Module];
242
243 //
244 //! Before returning, grab the temperature trims.
245 //
246 priv_temp_trims.ui32.ui32CalibrationTemperature =
247 am_hal_flash_load_ui32((uint32_t*)AM_HAL_ADC_CALIB_TEMP_ADDR);
248 priv_temp_trims.ui32.ui32CalibrationVoltage =
249 am_hal_flash_load_ui32((uint32_t*)AM_HAL_ADC_CALIB_AMBIENT_ADDR);
250 priv_temp_trims.ui32.ui32CalibrationOffset =
251 am_hal_flash_load_ui32((uint32_t*)AM_HAL_ADC_CALIB_ADC_OFFSET_ADDR);
252
253 if ( (priv_temp_trims.ui32.ui32CalibrationTemperature == 0xffffffff) ||
254 (priv_temp_trims.ui32.ui32CalibrationVoltage == 0xffffffff) ||
255 (priv_temp_trims.ui32.ui32CalibrationOffset == 0xffffffff) )
256 {
257 //
258 //! @note Since the device has not been calibrated on the tester, we'll load
259 //! default calibration values. These default values should result
260 //! in worst-case temperature measurements of +-6 degress C.
261 //
262 priv_temp_trims.flt.fCalibrationTemperature = AM_HAL_ADC_CALIB_TEMP_DEFAULT;
263 priv_temp_trims.flt.fCalibrationVoltage = AM_HAL_ADC_CALIB_AMBIENT_DEFAULT;
264 priv_temp_trims.flt.fCalibrationOffset = AM_HAL_ADC_CALIB_ADC_OFFSET_DEFAULT;
265 priv_temp_trims.ui32.bMeasured = false;
266 }
267 else
268 {
269 priv_temp_trims.ui32.bMeasured = true;
270 }
271
272 //
273 //! Return the status.
274 //
275 return AM_HAL_STATUS_SUCCESS;
276 }
277
278 //*****************************************************************************
279 //
280 // @brief MSPI deinitialization function
281 // @note This function accepts a handle to an instance and de-initializes the
282 // interface.
283 //
284 // @param pHandle - returns the handle for the module instance.
285 //
286 // @return status - generic or interface specific status.
287 //
288 //*****************************************************************************
289 uint32_t
am_hal_adc_deinitialize(void * pHandle)290 am_hal_adc_deinitialize(void *pHandle)
291 {
292 uint32_t status = AM_HAL_STATUS_SUCCESS;
293
294 #ifndef AM_HAL_DISABLE_API_VALIDATION
295 //
296 // Check the handle.
297 //
298 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
299 {
300 return AM_HAL_STATUS_INVALID_HANDLE;
301 }
302 #endif // AM_HAL_DISABLE_API_VALIDATION
303
304 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
305
306 if ( pADCState->prefix.s.bEnable )
307 {
308 status = am_hal_adc_disable(pHandle);
309 }
310
311 pADCState->prefix.s.bInit = false;
312
313 //
314 // Return the status.
315 //
316 return status;
317 }
318
319 //*****************************************************************************
320 //
321 // @brief ADC configuration function
322 // @note This function configures the ADC for operation.
323 //
324 // @param pHandle - handle for the module instance.
325 // @param psConfig - pointer to the configuration structure.
326 //
327 // @return status - generic or interface specific status.
328 //
329 //*****************************************************************************
330 uint32_t
am_hal_adc_configure(void * pHandle,am_hal_adc_config_t * psConfig)331 am_hal_adc_configure(void *pHandle,
332 am_hal_adc_config_t *psConfig)
333 {
334 uint32_t ui32Config;
335
336 #ifndef AM_HAL_DISABLE_API_VALIDATION
337 //
338 // Check the handle.
339 //
340 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
341 {
342 return AM_HAL_STATUS_INVALID_HANDLE;
343 }
344 #endif // AM_HAL_DISABLE_API_VALIDATION
345
346 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
347 uint32_t ui32Module = pADCState->ui32Module;
348
349 ui32Config = 0;
350
351 //
352 // Set the ADC clock source.
353 //
354 ui32Config |= _VAL2FLD(ADC_CFG_CLKSEL, psConfig->eClock);
355
356 //
357 // Set the ADC trigger polarity.
358 //
359 ui32Config |= _VAL2FLD(ADC_CFG_TRIGPOL, psConfig->ePolarity);
360
361 //
362 // Set the ADC trigger.
363 //
364 ui32Config |= _VAL2FLD(ADC_CFG_TRIGSEL, psConfig->eTrigger);
365
366 //
367 // Set the ADC reference voltage.
368 //
369 ui32Config |= _VAL2FLD(ADC_CFG_REFSEL, psConfig->eReference);
370
371 //
372 // Set the Destructive FIFO read.
373 //
374 ui32Config |= _VAL2FLD(ADC_CFG_DFIFORDEN, 1);
375
376 //
377 // Set the ADC clock mode.
378 //
379 ui32Config |= _VAL2FLD(ADC_CFG_CKMODE, psConfig->eClockMode);
380
381 //
382 // Set the ADC low power mode.
383 //
384 ui32Config |= _VAL2FLD(ADC_CFG_LPMODE, psConfig->ePowerMode);
385
386 //
387 // Set the ADC repetition mode.
388 //
389 ui32Config |= _VAL2FLD(ADC_CFG_RPTEN, psConfig->eRepeat);
390
391 //
392 // Set the configuration in the ADC peripheral.
393 //
394 ADCn(ui32Module)->CFG = ui32Config;
395
396 //
397 // Return status.
398 //
399 return AM_HAL_STATUS_SUCCESS;
400 }
401
402 //*****************************************************************************
403 //
404 // @brief ADC slot configuration function
405 // @note This function configures the ADC slot for operation.
406 //
407 // @param pHandle - handle for the module instance.
408 // @param ui32SlotNumber - slot number
409 // @param pSlotConfig - pointer to the configuration structure.
410 //
411 // @return status - generic or interface specific status.
412 //
413 //*****************************************************************************
414 uint32_t
am_hal_adc_configure_slot(void * pHandle,uint32_t ui32SlotNumber,am_hal_adc_slot_config_t * pSlotConfig)415 am_hal_adc_configure_slot(void *pHandle,
416 uint32_t ui32SlotNumber,
417 am_hal_adc_slot_config_t *pSlotConfig)
418 {
419 uint32_t ui32Config;
420 uint32_t ui32RegOffset;
421
422 #ifndef AM_HAL_DISABLE_API_VALIDATION
423 //
424 // Check the handle.
425 //
426 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
427 {
428 return AM_HAL_STATUS_INVALID_HANDLE;
429 }
430 #endif // AM_HAL_DISABLE_API_VALIDATION
431
432 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
433 uint32_t ui32Module = pADCState->ui32Module;
434
435 #ifndef AM_HAL_DISABLE_API_VALIDATION
436 //
437 // Check the slot number.
438 //
439 if ( ui32SlotNumber >= AM_HAL_ADC_MAX_SLOTS )
440 {
441 return AM_HAL_STATUS_OUT_OF_RANGE;
442 }
443 #endif // AM_HAL_DISABLE_API_VALIDATION
444
445 ui32Config = 0;
446
447 //
448 // Set the measurements to average
449 //
450 ui32Config |= _VAL2FLD(ADC_SL0CFG_ADSEL0, pSlotConfig->eMeasToAvg);
451
452 //
453 // Set the precision mode.
454 //
455 ui32Config |= _VAL2FLD(ADC_SL0CFG_PRMODE0, pSlotConfig->ePrecisionMode);
456
457 //
458 // Set the channel.
459 //
460 ui32Config |= _VAL2FLD(ADC_SL0CFG_CHSEL0, pSlotConfig->eChannel);
461
462 //
463 // Enable window comparison if configured.
464 //
465 ui32Config |= _VAL2FLD(ADC_SL0CFG_WCEN0, pSlotConfig->bWindowCompare);
466
467 //
468 // Enable the slot if configured.
469 //
470 ui32Config |= _VAL2FLD(ADC_SL0CFG_SLEN0, pSlotConfig->bEnabled);
471
472 //
473 // Locate the correct register for this ADC slot.
474 //
475 ui32RegOffset = ((uint32_t)&ADCn(ui32Module)->SL0CFG) + (4 * ui32SlotNumber);
476
477 //
478 // Write the register with the caller's configuration value.
479 //
480 AM_REGVAL(ui32RegOffset) = ui32Config;
481
482 //
483 // Update the nubmer of slots configured.
484 //
485 g_ADCSlotsConfigured++;
486
487 //
488 // Return the status.
489 //
490 return AM_HAL_STATUS_SUCCESS;
491 }
492
493 //*****************************************************************************
494 //
495 // @brief ADC DMA configuration function
496 //
497 // @param pHandle - handle for the module instance.
498 // @param pDMAConfig - pointer to the configuration structure.
499 //
500 // This function configures the ADC DMA for operation.
501 //
502 // @return status - generic or interface specific status.
503 //
504 //*****************************************************************************
505 uint32_t
am_hal_adc_configure_dma(void * pHandle,am_hal_adc_dma_config_t * pDMAConfig)506 am_hal_adc_configure_dma(void *pHandle,
507 am_hal_adc_dma_config_t *pDMAConfig)
508 {
509 uint32_t ui32Config;
510
511 #ifndef AM_HAL_DISABLE_API_VALIDATION
512 //
513 // Check the handle.
514 //
515 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
516 {
517 return AM_HAL_STATUS_INVALID_HANDLE;
518 }
519 #endif // AM_HAL_DISABLE_API_VALIDATION
520
521 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
522
523 #ifndef AM_HAL_DISABLE_API_VALIDATION
524 //
525 // Check for DMA to/from DTCM.
526 //
527 if ( (pDMAConfig->ui32TargetAddress >= AM_HAL_FLASH_DTCM_START) &&
528 (pDMAConfig->ui32TargetAddress <= AM_HAL_FLASH_DTCM_END) )
529 {
530 return AM_HAL_STATUS_OUT_OF_RANGE;
531 }
532 #endif // AM_HAL_DISABLE_API_VALIDATION
533
534 ui32Config = 0;
535
536 //
537 // Configure the DMA complete power-off.
538 //
539 ui32Config |= _VAL2FLD(ADC_DMACFG_DPWROFF, 0); // DPWROFF not supported!
540
541 //
542 // Configure the data to be transferred.
543 //
544 if ( g_ADCSlotsConfigured > 1 )
545 {
546 // Need slot number to distinguish between slot results.
547 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_DIS);
548 }
549 else
550 {
551 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAMSK, ADC_DMACFG_DMAMSK_EN);
552 }
553
554 //
555 // Enable DMA Halt on Status (DMAERR or DMACPL) by default.
556 //
557 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAHONSTAT, ADC_DMACFG_DMAHONSTAT_EN);
558
559 //
560 // Configure the DMA dynamic priority handling.
561 //
562 ui32Config |= _VAL2FLD(ADC_DMACFG_DMADYNPRI, pDMAConfig->bDynamicPriority);
563
564 //
565 // Configure the DMA static priority.
566 //
567 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAPRI, pDMAConfig->ePriority);
568
569 //
570 // Enable the DMA (does not start until ADC is enabled and triggered).
571 //
572 ui32Config |= _VAL2FLD(ADC_DMACFG_DMAEN, ADC_DMACFG_DMAEN_EN);
573
574 //
575 // Set the DMA configuration.
576 //
577 ADCn(ui32Module)->DMACFG = ui32Config;
578
579 //
580 // Set the DMA transfer count.
581 //
582 ADCn(ui32Module)->DMATOTCOUNT_b.TOTCOUNT = pDMAConfig->ui32SampleCount;
583
584 //
585 // Set the DMA target address.
586 //
587 ADCn(ui32Module)->DMATARGADDR = pDMAConfig->ui32TargetAddress;
588
589 //
590 // Set the DMA trigger on FIFO 75% full.
591 //
592 ADCn(ui32Module)->DMATRIGEN = ADC_DMATRIGEN_DFIFO75_Msk;
593
594 //
595 // Return the status.
596 //
597 return AM_HAL_STATUS_SUCCESS;
598 }
599
600 //*****************************************************************************
601 //
602 // @brief ADC device specific control function.
603 //
604 // @param pHandle - handle for the module instance.
605 // @param eRequest - enum request type
606 // @param pArgs - pointer to pArgs (array of three floats)
607 //
608 // This function provides for special control functions for the ADC operation.
609 //
610 // @return status - generic or interface specific status.
611 //
612 //*****************************************************************************
am_hal_adc_control(void * pHandle,am_hal_adc_request_e eRequest,void * pArgs)613 uint32_t am_hal_adc_control(void *pHandle,
614 am_hal_adc_request_e eRequest,
615 void *pArgs)
616 {
617
618 #ifndef AM_HAL_DISABLE_API_VALIDATION
619 //
620 // Check the handle.
621 //
622 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
623 {
624 return AM_HAL_STATUS_INVALID_HANDLE;
625 }
626 #endif // AM_HAL_DISABLE_API_VALIDATION
627
628 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
629
630 switch ( eRequest )
631 {
632 case AM_HAL_ADC_REQ_WINDOW_CONFIG:
633 {
634 am_hal_adc_window_config_t *pWindowConfig = (am_hal_adc_window_config_t *)pArgs;
635
636 #ifndef AM_HAL_DISABLE_API_VALIDATION
637 //
638 // Check the window limits.
639 //
640 if ( (pWindowConfig->ui32Upper > ADC_WULIM_ULIM_Msk) ||
641 (pWindowConfig->ui32Lower > ADC_WLLIM_LLIM_Msk) )
642 {
643 return AM_HAL_STATUS_OUT_OF_RANGE;
644 }
645 #endif // AM_HAL_DISABLE_API_VALIDATION
646 //
647 // Set the window comparison upper and lower limits.
648 //
649 ADCn(ui32Module)->WULIM = _VAL2FLD(ADC_WULIM_ULIM, pWindowConfig->ui32Upper);
650 ADCn(ui32Module)->WLLIM = _VAL2FLD(ADC_WLLIM_LLIM, pWindowConfig->ui32Lower);
651
652 //
653 // Set the window scale per precision mode if indicated.
654 //
655 ADCn(ui32Module)->SCWLIM = _VAL2FLD(ADC_SCWLIM_SCWLIMEN,
656 pWindowConfig->bScaleLimits);
657 }
658 break;
659
660 case AM_HAL_ADC_REQ_TEMP_CELSIUS_GET:
661 //
662 // pArgs must point to an array of 3 floats. To assure that the
663 // array is valid, upon calling the 3rd float (pArgs[2]) must be
664 // set to the value -123.456F.
665 //
666 if ( pArgs != NULL )
667 {
668 float *pfArray = (float*)pArgs;
669 float fTemp, fCalibration_temp, fCalibration_voltage, fCalibration_offset, fVoltage;
670
671 if ( pfArray[2] == -123.456F )
672 {
673 //
674 // The caller has provided a voltage as determined from the
675 // sample. The sample is scaled up by the reference voltage
676 // used on the device and then scaled down by the number of
677 // sample bits.
678 // i.e. scaled by AM_HAL_ADC_VREF / (1 << number_bits).
679 //
680 // Get the scaled voltage obtained from the ADC sample.
681 //
682 fVoltage = pfArray[0];
683
684 //
685 // Compute the calibrated temperature via the equation:
686 // T = m * Vmeas + T1 - m(V1 + Voff)
687 // m = AM_HAL_ADC_TEMPSENSOR_SLOPE (degK / V)
688 // Vmeas = The measured voltage (as based on the ADC code)
689 // T1 = Calibration temperature
690 // V1 = Calibration voltage (stored in volts)
691 // Voff = Calibration offset (stored in volts)
692 //
693 fCalibration_temp = priv_temp_trims.flt.fCalibrationTemperature;
694 fCalibration_voltage = priv_temp_trims.flt.fCalibrationVoltage;
695 fCalibration_offset = priv_temp_trims.flt.fCalibrationOffset;
696
697 //
698 // Compute the temperature in K
699 //
700 if ( g_fTempEqnTerms == 0.0F )
701 {
702 //
703 // The 2nd and 3rd terms of the temperature equation are
704 // consistent for a given device, so compute them only
705 // the first time and save.
706 //
707 g_fTempEqnTerms = -1.0F * AM_HAL_ADC_TEMPSENSOR_SLOPE;
708 g_fTempEqnTerms *= (fCalibration_voltage + fCalibration_offset);
709 g_fTempEqnTerms += fCalibration_temp;
710 }
711
712 //
713 // Determine the temperature in K by factoring
714 // in the supplied sample voltage
715 //
716 fTemp = AM_HAL_ADC_TEMPSENSOR_SLOPE * fVoltage;
717 fTemp += g_fTempEqnTerms;
718
719 //
720 // Give it back to the caller in Celsius.
721 //
722 pfArray[1] = fTemp - 273.15f;
723 }
724 else
725 {
726 return AM_HAL_STATUS_INVALID_OPERATION;
727 }
728 }
729 else
730 {
731 return AM_HAL_STATUS_INVALID_ARG;
732 }
733 break;
734
735 case AM_HAL_ADC_REQ_TEMP_TRIMS_GET:
736 //
737 // pArgs must point to an array of 4 floats. To assure that the
738 // array is valid, upon calling the 4th float (pArgs[3]) must be
739 // set to the value -123.456.
740 // On return, pArgs[3] is set to 1 if the returned values are
741 // calibrated, or 0 if default calibration values.
742 //
743 if ( pArgs != NULL )
744 {
745 float *pfArray = (float*)pArgs;
746 if ( pfArray[3] == -123.456F )
747 {
748 //
749 // Return trim temperature as a float.
750 //
751 pfArray[0] = priv_temp_trims.flt.fCalibrationTemperature;
752
753 //
754 // Return trim voltage as a float.
755 //
756 pfArray[1] = priv_temp_trims.flt.fCalibrationVoltage;
757
758 //
759 // Return trim ADC offset voltage (in volts) as a float.
760 //
761 pfArray[2] = priv_temp_trims.flt.fCalibrationOffset;
762
763 //
764 // Set the calibrated or uncalibrated flag
765 //
766 *(uint32_t*)&pfArray[3] = priv_temp_trims.ui32.bMeasured;
767 }
768 else
769 {
770 return AM_HAL_STATUS_INVALID_OPERATION;
771 }
772 }
773 else
774 {
775 return AM_HAL_STATUS_INVALID_ARG;
776 }
777 break;
778
779 default:
780 return AM_HAL_STATUS_INVALID_ARG;
781 }
782
783 //
784 // Return status.
785 //
786 return AM_HAL_STATUS_SUCCESS;
787 }
788
789 //*****************************************************************************
790 //
791 // @brief ADC enable function
792 //
793 // @param pHandle - handle for the module instance.
794 //
795 // This function enables the ADC operation.
796 //
797 // @return status - generic or interface specific status.
798 //
799 //*****************************************************************************
800 uint32_t
am_hal_adc_enable(void * pHandle)801 am_hal_adc_enable(void *pHandle)
802 {
803
804 #ifndef AM_HAL_DISABLE_API_VALIDATION
805 //
806 // Check the handle.
807 //
808 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
809 {
810 return AM_HAL_STATUS_INVALID_HANDLE;
811 }
812 #endif
813 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
814 uint32_t ui32Module = pADCState->ui32Module;
815
816 if ( pADCState->prefix.s.bEnable )
817 {
818 return AM_HAL_STATUS_SUCCESS;
819 }
820
821 //
822 // Enable the ADC.
823 //
824 ADCn(ui32Module)->CFG_b.ADCEN = 0x1;
825
826 //
827 // Set flag to indicate module is enabled.
828 //
829 pADCState->prefix.s.bEnable = true;
830
831 //
832 // Return the status.
833 //
834 return AM_HAL_STATUS_SUCCESS;
835 }
836
837 //*****************************************************************************
838 //
839 // @brief ADC disable function
840 //
841 // @param pHandle - handle for the module instance.
842 //
843 // This function disables the ADC operation.
844 //
845 // @return status - generic or interface specific status.
846 //
847 //*****************************************************************************
848 uint32_t
am_hal_adc_disable(void * pHandle)849 am_hal_adc_disable(void *pHandle)
850 {
851
852 #ifndef AM_HAL_DISABLE_API_VALIDATION
853 //
854 // Check the handle.
855 //
856 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
857 {
858 return AM_HAL_STATUS_INVALID_HANDLE;
859 }
860 #endif // AM_HAL_DISABLE_API_VALIDATION
861 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
862 uint32_t ui32Module = pADCState->ui32Module;
863
864 //
865 // disable dma in progress and clear status
866 //
867 ADCn(ui32Module)->DMACFG_b.DMAEN = 0;
868 ADCn(ui32Module)->DMASTAT = 0 ;
869
870 //
871 // Disable the ADC.
872 //
873 ADCn(ui32Module)->CFG_b.ADCEN = 0x0;
874
875 //
876 // Set flag to indicate module is disabled.
877 //
878 pADCState->prefix.s.bEnable = false;
879
880 //
881 // Return the status.
882 //
883 return AM_HAL_STATUS_SUCCESS;
884 }
885
886 //*****************************************************************************
887 //
888 // @brief ADC status function
889 //
890 // @param pHandle - handle for the interface.
891 // @param pStatus - returns status here
892 //
893 // This function returns the current status of the DMA operation.
894 //
895 // @return status - DMA status flags.
896 //
897 //*****************************************************************************
898 uint32_t
am_hal_adc_status_get(void * pHandle,am_hal_adc_status_t * pStatus)899 am_hal_adc_status_get(void *pHandle, am_hal_adc_status_t *pStatus )
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 uint32_t ui32Module = ((am_hal_adc_state_t *)pHandle)->ui32Module;
912
913 //
914 // Get the power status.
915 //
916 pStatus->bPoweredOn = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
917 _VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_ON);
918
919 //
920 // Get the low power mode 1 status.
921 //
922 pStatus->bLPMode1 = (ADCn(ui32Module)->STAT & ADC_STAT_PWDSTAT_Msk) ==
923 _VAL2FLD(ADC_STAT_PWDSTAT, ADC_STAT_PWDSTAT_POWERED_DOWN);
924
925 //
926 // Get the DMA status.
927 //
928 pStatus->bErr = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMAERR_Msk) > 0);
929 pStatus->bCmp = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMACPL_Msk) > 0);
930 pStatus->bTIP = ((ADCn(ui32Module)->DMASTAT & ADC_DMASTAT_DMATIP_Msk) > 0);
931
932 //
933 // Return the status.
934 //
935 return AM_HAL_STATUS_SUCCESS;
936 }
937
938 //*****************************************************************************
939 //
940 // @brief ADC enable interrupts function
941 //
942 // @param pHandle - handle for the interface.
943 // @param ui32IntMask - ADC interrupt mask.
944 //
945 // This function enables the specific indicated interrupts.
946 //
947 // @return status - generic or interface specific status.
948 //
949 //*****************************************************************************
950 uint32_t
am_hal_adc_interrupt_enable(void * pHandle,uint32_t ui32IntMask)951 am_hal_adc_interrupt_enable(void *pHandle, uint32_t ui32IntMask)
952 {
953
954 #ifndef AM_HAL_DISABLE_API_VALIDATION
955 //
956 // Check the handle.
957 //
958 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
959 {
960 return AM_HAL_STATUS_INVALID_HANDLE;
961 }
962 #endif // AM_HAL_DISABLE_API_VALIDATION
963
964 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
965
966 //
967 // Enable the interrupts.
968 //
969 ADCn(ui32Module)->INTEN |= ui32IntMask;
970
971 //
972 // Return the status.
973 //
974 return AM_HAL_STATUS_SUCCESS;
975 }
976
977 //*****************************************************************************
978 //
979 // @brief ADC disable interrupts function
980 //
981 // @param pHandle - handle for the interface.
982 // @param ui32IntMask - ADC interrupt mask.
983 //
984 // This function disable the specific indicated interrupts.
985 //
986 // @return status - generic or interface specific status.
987 //
988 //*****************************************************************************
989 uint32_t
am_hal_adc_interrupt_disable(void * pHandle,uint32_t ui32IntMask)990 am_hal_adc_interrupt_disable(void *pHandle, uint32_t ui32IntMask)
991 {
992
993 #ifndef AM_HAL_DISABLE_API_VALIDATION
994 //
995 // Check the handle.
996 //
997 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
998 {
999 return AM_HAL_STATUS_INVALID_HANDLE;
1000 }
1001 #endif // AM_HAL_DISABLE_API_VALIDATION
1002
1003 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1004
1005 //
1006 // Disable the interrupts.
1007 //
1008 ADCn(ui32Module)->INTEN &= ~ui32IntMask;
1009
1010 //
1011 // Return the status.
1012 //
1013 return AM_HAL_STATUS_SUCCESS;
1014 }
1015
1016 //*****************************************************************************
1017 //
1018 // @brief ADC interrupt status function
1019 //
1020 // @param pHandle - handle for the interface.
1021 // @param pui32Status - returns interrupts enabled here
1022 // @param bEnabledOnly - if true, only return enabled interrupts
1023 //
1024 // This function returns the specific indicated interrupt status.
1025 //
1026 // @return status - generic or interface specific status.
1027 //
1028 //*****************************************************************************
1029 uint32_t
am_hal_adc_interrupt_status(void * pHandle,uint32_t * pui32Status,bool bEnabledOnly)1030 am_hal_adc_interrupt_status(void *pHandle,
1031 uint32_t *pui32Status,
1032 bool bEnabledOnly)
1033 {
1034
1035 #ifndef AM_HAL_DISABLE_API_VALIDATION
1036 //
1037 // Check the handle.
1038 //
1039 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1040 {
1041 return AM_HAL_STATUS_INVALID_HANDLE;
1042 }
1043 #endif // AM_HAL_DISABLE_API_VALIDATION
1044
1045 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1046
1047 //
1048 // if requested, only return the interrupts that are enabled.
1049 //
1050 if ( bEnabledOnly )
1051 {
1052 uint32_t ui32RetVal = ADCn(ui32Module)->INTSTAT;
1053 *pui32Status = ADCn(ui32Module)->INTEN & ui32RetVal;
1054 }
1055 else
1056 {
1057 *pui32Status = ADCn(ui32Module)->INTSTAT;
1058 }
1059
1060 //
1061 // Return the status.
1062 //
1063 return AM_HAL_STATUS_SUCCESS;
1064 }
1065
1066
1067 //*****************************************************************************
1068 //
1069 // @brief ADC interrupt clear
1070 //
1071 // @param pHandle - handle for the interface.
1072 // @param ui32IntMask - uint32_t for interrupts to clear
1073 //
1074 // This function clears the interrupts for the given peripheral.
1075 //
1076 // @return status - generic or interface specific status.
1077 //
1078 //*****************************************************************************
1079 uint32_t
am_hal_adc_interrupt_clear(void * pHandle,uint32_t ui32IntMask)1080 am_hal_adc_interrupt_clear(void *pHandle, uint32_t ui32IntMask)
1081 {
1082
1083 #ifndef AM_HAL_DISABLE_API_VALIDATION
1084 //
1085 // Check the handle.
1086 //
1087 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1088 {
1089 return AM_HAL_STATUS_INVALID_HANDLE;
1090 }
1091 #endif // AM_HAL_DISABLE_API_VALIDATION
1092
1093 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1094 //
1095 // Clear the interrupts.
1096 //
1097 ADCn(ui32Module)->INTCLR = ui32IntMask;
1098
1099 //
1100 // Return the status.
1101 //
1102 return AM_HAL_STATUS_SUCCESS;
1103 }
1104
1105 //*****************************************************************************
1106 //
1107 // @brief ADC sample read function
1108 //
1109 // @param pHandle - handle for the module instance.
1110 // @param bFullSample - true to get a full sample including
1111 // the fractional part.
1112 // @param pui32InSampleBuffer - Ptr to the input sample buffer.
1113 // If NULL then samples will be read directly
1114 // from the FIFO.
1115 // @param pui32InOutNumberSamples - Ptr to variable containing the number of
1116 // samples.
1117 // @param pui32OutBuffer - Ptr to the required output sample buffer.
1118 //
1119 // This function reads samples from the ADC FIFO or an SRAM sample buffer
1120 // returned by a DMA operation.
1121 //
1122 // @return status - generic or interface specific status.
1123 //
1124 //*****************************************************************************
am_hal_adc_samples_read(void * pHandle,bool bFullSample,uint32_t * pui32InSampleBuffer,uint32_t * pui32InOutNumberSamples,am_hal_adc_sample_t * pui32OutBuffer)1125 uint32_t am_hal_adc_samples_read(void *pHandle,
1126 bool bFullSample,
1127 uint32_t *pui32InSampleBuffer,
1128 uint32_t *pui32InOutNumberSamples,
1129 am_hal_adc_sample_t *pui32OutBuffer)
1130 {
1131 uint32_t ui32Sample;
1132
1133 #ifndef AM_HAL_DISABLE_API_VALIDATION
1134 //
1135 // Check the handle.
1136 //
1137 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1138 {
1139 return AM_HAL_STATUS_INVALID_HANDLE;
1140 }
1141
1142 //
1143 // Check the output sample buffer pointer.
1144 //
1145 if ( NULL == pui32OutBuffer )
1146 {
1147 return AM_HAL_STATUS_INVALID_ARG;
1148 }
1149 #endif // AM_HAL_DISABLE_API_VALIDATION
1150
1151 uint32_t ui32RequestedSamples = *pui32InOutNumberSamples;
1152 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1153
1154 *pui32InOutNumberSamples = 0;
1155
1156 //
1157 // Check if we are reading directly from FIFO or DMA SRAM buffer.
1158 //
1159 if ( NULL == pui32InSampleBuffer )
1160 {
1161 //
1162 // Grab a value from the ADC FIFO
1163 //
1164 do
1165 {
1166 ui32Sample = ADCn(ui32Module)->FIFOPR;
1167 pui32OutBuffer->ui32Slot = AM_HAL_ADC_FIFO_SLOT(ui32Sample);
1168 pui32OutBuffer->ui32Sample = bFullSample ?
1169 AM_HAL_ADC_FIFO_FULL_SAMPLE(ui32Sample) :
1170 AM_HAL_ADC_FIFO_SAMPLE(ui32Sample);
1171 pui32OutBuffer++;
1172 (*pui32InOutNumberSamples)++;
1173 } while ((AM_HAL_ADC_FIFO_COUNT(ui32Sample) > 0) &&
1174 (*pui32InOutNumberSamples < ui32RequestedSamples));
1175 }
1176 else
1177 {
1178 //
1179 // Process the samples from the provided sample buffer
1180 //
1181 do
1182 {
1183 pui32OutBuffer->ui32Slot = AM_HAL_ADC_FIFO_SLOT(*pui32InSampleBuffer);
1184 pui32OutBuffer->ui32Sample = AM_HAL_ADC_FIFO_SAMPLE(*pui32InSampleBuffer);
1185 pui32InSampleBuffer++;
1186 pui32OutBuffer++;
1187 (*pui32InOutNumberSamples)++;
1188 } while (*pui32InOutNumberSamples < ui32RequestedSamples);
1189 }
1190
1191 //
1192 // Return FIFO valid bits.
1193 //
1194 return AM_HAL_STATUS_SUCCESS;
1195 }
1196
1197 //*****************************************************************************
1198 //
1199 // @brief Issue Software Trigger to the ADC.
1200 //
1201 // @param pHandle - handle for the module instance.
1202 //
1203 // This function triggers the ADC operation.
1204 //
1205 // @return status - generic or interface specific status.
1206 //
1207 //*****************************************************************************
1208 uint32_t
am_hal_adc_sw_trigger(void * pHandle)1209 am_hal_adc_sw_trigger(void *pHandle)
1210 {
1211
1212 #ifndef AM_HAL_DISABLE_API_VALIDATION
1213 //
1214 // Check the handle.
1215 //
1216 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1217 {
1218 return AM_HAL_STATUS_INVALID_HANDLE;
1219 }
1220 #endif // AM_HAL_DISABLE_API_VALIDATION
1221
1222 uint32_t ui32Module = ((am_hal_adc_state_t*)pHandle)->ui32Module;
1223
1224 //
1225 // Write to the Software trigger register in the ADC.
1226 //
1227 ADCn(ui32Module)->SWT = 0x37;
1228
1229 //
1230 // Return the status.
1231 //
1232 return AM_HAL_STATUS_SUCCESS;
1233 }
1234
1235 //*****************************************************************************
1236 //
1237 // @brief ADC power control function
1238 //
1239 // @param pHandle - handle for the interface.
1240 // @param ePowerState - the desired power state to move the peripheral to.
1241 // @param bRetainState - flag (if true) to save/restore peripheral state upon
1242 // power state change.
1243 //
1244 // This function updates the peripheral to a given power state.
1245 //
1246 // @return status - generic or interface specific status.
1247 //
1248 //*****************************************************************************
1249 uint32_t
am_hal_adc_power_control(void * pHandle,am_hal_sysctrl_power_state_e ePowerState,bool bRetainState)1250 am_hal_adc_power_control(void *pHandle,
1251 am_hal_sysctrl_power_state_e ePowerState,
1252 bool bRetainState)
1253 {
1254
1255 #ifndef AM_HAL_DISABLE_API_VALIDATION
1256 //
1257 // Check the handle.
1258 //
1259 if ( !AM_HAL_ADC_CHK_HANDLE(pHandle) )
1260 {
1261 return AM_HAL_STATUS_INVALID_HANDLE;
1262 }
1263 #endif // AM_HAL_DISABLE_API_VALIDATION
1264
1265 am_hal_adc_state_t *pADCState = (am_hal_adc_state_t *)pHandle;
1266 uint32_t ui32Module = pADCState->ui32Module;
1267
1268 //
1269 // Decode the requested power state and update MSPI operation accordingly.
1270 //
1271 switch (ePowerState)
1272 {
1273 case AM_HAL_SYSCTRL_WAKE:
1274 if ( bRetainState && !pADCState->registerState.bValid )
1275 {
1276 return AM_HAL_STATUS_INVALID_OPERATION;
1277 }
1278
1279 //
1280 // Enable the ADC power domain.
1281 //
1282 am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_ADC);
1283
1284 if ( bRetainState )
1285 {
1286 ADCn(ui32Module)->SL0CFG = pADCState->registerState.regSL0CFG;
1287 ADCn(ui32Module)->SL1CFG = pADCState->registerState.regSL1CFG;
1288 ADCn(ui32Module)->SL2CFG = pADCState->registerState.regSL2CFG;
1289 ADCn(ui32Module)->SL3CFG = pADCState->registerState.regSL3CFG;
1290 ADCn(ui32Module)->SL4CFG = pADCState->registerState.regSL4CFG;
1291 ADCn(ui32Module)->SL5CFG = pADCState->registerState.regSL5CFG;
1292 ADCn(ui32Module)->SL6CFG = pADCState->registerState.regSL6CFG;
1293 ADCn(ui32Module)->SL7CFG = pADCState->registerState.regSL7CFG;
1294 ADCn(ui32Module)->WULIM = pADCState->registerState.regWULIM;
1295 ADCn(ui32Module)->WLLIM = pADCState->registerState.regWLLIM;
1296 ADCn(ui32Module)->INTEN = 0;
1297 ADCn(ui32Module)->CFG = pADCState->registerState.regCFG & (~ADC_CFG_ADCEN_Msk);
1298 ADCn(ui32Module)->CFG_b.ADCEN = _FLD2VAL(ADC_CFG_ADCEN, pADCState->registerState.regCFG);
1299 ADCn(ui32Module)->INTEN = pADCState->registerState.regINTEN;
1300 pADCState->registerState.bValid = false;
1301 }
1302 break;
1303
1304 case AM_HAL_SYSCTRL_NORMALSLEEP:
1305 case AM_HAL_SYSCTRL_DEEPSLEEP:
1306 if ( bRetainState )
1307 {
1308 pADCState->registerState.regSL0CFG = ADCn(ui32Module)->SL0CFG;
1309 pADCState->registerState.regSL1CFG = ADCn(ui32Module)->SL1CFG;
1310 pADCState->registerState.regSL2CFG = ADCn(ui32Module)->SL2CFG;
1311 pADCState->registerState.regSL3CFG = ADCn(ui32Module)->SL3CFG;
1312 pADCState->registerState.regSL4CFG = ADCn(ui32Module)->SL4CFG;
1313 pADCState->registerState.regSL5CFG = ADCn(ui32Module)->SL5CFG;
1314 pADCState->registerState.regSL6CFG = ADCn(ui32Module)->SL6CFG;
1315 pADCState->registerState.regSL7CFG = ADCn(ui32Module)->SL7CFG;
1316 pADCState->registerState.regWULIM = ADCn(ui32Module)->WULIM;
1317 pADCState->registerState.regWLLIM = ADCn(ui32Module)->WLLIM;
1318 pADCState->registerState.regINTEN = ADCn(ui32Module)->INTEN;
1319 pADCState->registerState.regCFG = ADCn(ui32Module)->CFG;
1320
1321 pADCState->registerState.bValid = true;
1322 }
1323
1324 //
1325 // Disable the ADC power domain.
1326 //
1327 am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC);
1328 break;
1329
1330 default:
1331 return AM_HAL_STATUS_INVALID_ARG;
1332 }
1333
1334 //
1335 // Return the status.
1336 //
1337 return AM_HAL_STATUS_SUCCESS;
1338 }
1339
1340 //*****************************************************************************
1341 //
1342 // End Doxygen group.
1343 //! @}
1344 //
1345 //*****************************************************************************
1346