1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\r
6 * This source code is free software; you can redistribute it and/or modify it
\r
7 * under the terms of the GNU General Public License version 2 as published by the
\r
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
\r
10 * This program is distributed in the hope that it will be useful, but
\r
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
\r
14 * -------------------------------- Arctic Core ------------------------------*/
\r
25 //#include "System.h"
\r
26 #include "mpc55xx.h"
\r
27 #include "Modules.h"
\r
32 #if defined(USE_KERNEL)
\r
49 vuint32_t ADC_REG:16;
\r
50 vuint32_t ADC_REG_ADDR:8;
\r
52 }Adc_RegisterWriteType;
\r
64 vuint32_t MESSAGE_TAG:4;
\r
66 vuint32_t ADC_REG_ADDR:8;
\r
68 }Adc_RegisterReadType;
\r
84 ADC_EQADC_NBR_OF_QUEUES
\r
85 }Adc_eQADCQueueType;
\r
89 EQADC_CFIFO_STATUS_IDLE = 0,
\r
90 EQADC_CFIFO_STATUS_WAITINGFOR_TRIGGER = 0x2,
\r
91 EQADC_CFIFO_STATUS_TRIGGERED = 0x3
\r
92 }Adc_EQADCQueueStatusType;
\r
95 typedef int16_t Adc_EQADCRegister;
\r
104 }Adc_EQADCRegisterType;
\r
106 /* Function prototypes. */
\r
107 static void Adc_ConfigureEQADC (const Adc_ConfigType *ConfigPtr);
\r
108 static void Adc_ConfigureEQADCInterrupts (void);
\r
109 static void Adc_EQADCCalibrationSequence (void);
\r
110 static void Adc_WriteEQADCRegister (Adc_EQADCRegisterType reg, Adc_EQADCRegister value);
\r
111 static Adc_EQADCRegister Adc_ReadEQADCRegister (Adc_EQADCRegisterType reg);
\r
113 /* Development error checking. */
\r
114 static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group);
\r
115 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group);
\r
116 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr);
\r
117 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group);
\r
120 static Adc_StateType adcState = ADC_UNINIT;
\r
122 /* Pointer to configuration structure. */
\r
123 static const Adc_ConfigType *AdcConfigPtr;
\r
125 /* Command queue for calibration sequence. See 31.5.6 in reference manual. */
\r
126 const Adc_CommandType AdcCalibrationCommandQueue [] =
\r
128 /* Four samples of 25 % of (VRh - VRl). */
\r
130 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
131 .B.CHANNEL_NUMBER = 44
\r
134 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
135 .B.CHANNEL_NUMBER = 44
\r
138 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
139 .B.CHANNEL_NUMBER = 44
\r
142 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
143 .B.CHANNEL_NUMBER = 44
\r
145 /* Four samples of 75 % of (VRh - VRl). */
\r
147 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
148 .B.CHANNEL_NUMBER = 43
\r
151 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
152 .B.CHANNEL_NUMBER = 43
\r
155 .B.EOQ = 0, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
156 .B.CHANNEL_NUMBER = 43
\r
159 .B.EOQ = 1, .B.PAUSE = 0, .B.BN = 0, .B.CAL = 0, .B.MESSAGE_TAG = 0, .B.LST = ADC_CONVERSION_TIME_128_CLOCKS, .B.TSR = 0, .B.FMT = 0,
\r
160 .B.CHANNEL_NUMBER = 43
\r
164 /* DMA configuration for calibration sequence. */
\r
165 const struct tcd_t AdcCalibrationDMACommandConfig =
\r
167 .SADDR = (uint32_t)AdcCalibrationCommandQueue,
\r
169 .SSIZE = DMA_TRANSFER_SIZE_32BITS,
\r
171 .DSIZE = DMA_TRANSFER_SIZE_32BITS,
\r
172 .SOFF = sizeof(Adc_CommandType),
\r
173 .NBYTES = sizeof(Adc_CommandType),
\r
175 .DADDR = (vint32_t)&EQADC.CFPR[0].R,
\r
194 const struct tcd_t AdcCalibrationDMAResultConfig =
\r
196 .SADDR = (vint32_t)&EQADC.RFPR[0].R + 2,
\r
198 .SSIZE = DMA_TRANSFER_SIZE_16BITS,
\r
200 .DSIZE = DMA_TRANSFER_SIZE_16BITS,
\r
202 .NBYTES = sizeof(Adc_ValueGroupType),
\r
204 .DADDR = 0, /* Dynamic address, written later. */
\r
207 .DOFF = sizeof(Adc_ValueGroupType),
\r
223 #if (ADC_DEINIT_API == STD_ON)
\r
224 Std_ReturnType Adc_DeInit (const Adc_ConfigType *ConfigPtr)
\r
226 Adc_eQADCQueueType queue;
\r
227 Adc_GroupType group;
\r
228 boolean queueStopped;
\r
230 if (ADC_UNINIT != adcState)
\r
232 /* Stop all queues. */
\r
233 for (queue = ADC_EQADC_QUEUE_0; queue < ADC_EQADC_NBR_OF_QUEUES; queue++)
\r
235 /* Disable queue. */
\r
236 EQADC.CFCR[queue].B.MODE = 0;
\r
238 /* Wait for queue to enter idle state. */
\r
239 queueStopped = FALSE;
\r
240 /* TODO replace switch with bit pattern. */
\r
241 while (!queueStopped)
\r
245 case ADC_EQADC_QUEUE_0:
\r
246 queueStopped = (EQADC.CFSR.B.CFS0 == EQADC_CFIFO_STATUS_IDLE);
\r
248 case ADC_EQADC_QUEUE_1:
\r
249 queueStopped = (EQADC.CFSR.B.CFS1 == EQADC_CFIFO_STATUS_IDLE);
\r
251 case ADC_EQADC_QUEUE_2:
\r
252 queueStopped = (EQADC.CFSR.B.CFS2 == EQADC_CFIFO_STATUS_IDLE);
\r
254 case ADC_EQADC_QUEUE_3:
\r
255 queueStopped = (EQADC.CFSR.B.CFS3 == EQADC_CFIFO_STATUS_IDLE);
\r
257 case ADC_EQADC_QUEUE_4:
\r
258 queueStopped = (EQADC.CFSR.B.CFS4 == EQADC_CFIFO_STATUS_IDLE);
\r
260 case ADC_EQADC_QUEUE_5:
\r
261 queueStopped = (EQADC.CFSR.B.CFS5 == EQADC_CFIFO_STATUS_IDLE);
\r
264 /* We should never get here... Terminate loop. */
\r
265 queueStopped = TRUE;
\r
270 /* Disable eDMA requests for commands and results. */
\r
271 EQADC.IDCR[queue].B.CFFS = 0;
\r
272 EQADC.IDCR[queue].B.RFDS = 0;
\r
274 /* Disable FIFO fill requests. */
\r
275 EQADC.IDCR[queue].B.CFFE = 0;
\r
276 EQADC.IDCR[queue].B.RFDE = 0;
\r
278 /* Disable interrupts. */
\r
279 EQADC.IDCR[queue].B.RFOIE = 0;
\r
280 EQADC.IDCR[queue].B.CFUIE = 0;
\r
281 EQADC.IDCR[queue].B.TORIE = 0;
\r
282 EQADC.IDCR[queue].B.EOQIE = 0;
\r
285 /* Stop all DMA channels connected to EQADC. */
\r
286 for (group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)
\r
288 Dma_StopChannel (AdcConfigPtr->groupConfigPtr [group].dmaCommandChannel);
\r
289 Dma_StopChannel (AdcConfigPtr->groupConfigPtr [group].dmaResultChannel);
\r
291 /* Set group status to idle. */
\r
292 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
295 /* Disable EQADC. */
\r
296 Adc_WriteEQADCRegister (ADC0_CR, 0);
\r
298 /* Clean internal status. */
\r
299 AdcConfigPtr = (Adc_ConfigType *)NULL;
\r
300 adcState = ADC_UNINIT;
\r
306 Std_ReturnType Adc_Init (const Adc_ConfigType *ConfigPtr)
\r
308 Std_ReturnType returnValue;
\r
309 Adc_ChannelType channel;
\r
310 Adc_ChannelType channelId;
\r
311 Adc_GroupType group;
\r
312 Adc_CommandType *commandQueue;
\r
313 Adc_CommandType command;
\r
315 if (E_OK == Adc_CheckInit(ConfigPtr))
\r
317 /* First of all, store the location of the configuration data. */
\r
318 AdcConfigPtr = ConfigPtr;
\r
320 /* Start configuring the eQADC queues. */
\r
321 for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
\r
323 /* Loop through all channels and make the command queue. */
\r
324 for (channel = 0; channel < ConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)
\r
326 /* Get physical channel. */
\r
327 channelId = ConfigPtr->groupConfigPtr[group].channelList[channel];
\r
329 commandQueue = ConfigPtr->groupConfigPtr[group].commandBuffer;
\r
331 /* Begin with empty command. */
\r
334 /* Physical channel number. */
\r
335 command.B.CHANNEL_NUMBER = channelId;
\r
337 command.B.LST = ConfigPtr->channelConfigPtr [channel].adcChannelConvTime;
\r
338 /* Calibration feature. */
\r
339 command.B.CAL = ConfigPtr->channelConfigPtr [channel].adcChannelCalibrationEnable;
\r
340 /* Result buffer FIFO. The number of groups must not be greater than the number of queues. */
\r
341 command.B.MESSAGE_TAG = group;
\r
343 /* Write command to command queue. */
\r
344 commandQueue [channel].R = command.R;
\r
346 /* Last channel in group. Write EOQ and configure eQADC FIFO. */
\r
347 if (channel == (ConfigPtr->groupConfigPtr[group].numberOfChannels - 1))
\r
349 commandQueue [channel].B.EOQ = 1;
\r
355 Adc_ConfigureEQADC (ConfigPtr);
\r
357 /* Perform calibration of the ADC. */
\r
358 Adc_EQADCCalibrationSequence ();
\r
360 /* Configure DMA channels. */
\r
361 for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
\r
364 ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
366 Dma_ConfigureChannel ((struct tcd_t *)ConfigPtr->groupConfigPtr [group].groupDMAResults, ConfigPtr->groupConfigPtr [group].dmaResultChannel);
\r
367 Dma_ConfigureChannel ((struct tcd_t *)ConfigPtr->groupConfigPtr [group].groupDMACommands, ConfigPtr->groupConfigPtr [group].dmaCommandChannel);
\r
370 /* Start DMA channels. */
\r
371 for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
\r
373 /* Invalidate queues. */
\r
374 EQADC.CFCR[group].B.CFINV = 1;
\r
376 Dma_StartChannel (ConfigPtr->groupConfigPtr [group].dmaResultChannel);
\r
377 Dma_StartChannel (ConfigPtr->groupConfigPtr [group].dmaCommandChannel);
\r
380 Adc_ConfigureEQADCInterrupts ();
\r
382 /* Move on to INIT state. */
\r
383 adcState = ADC_INIT;
\r
384 returnValue = E_OK;
\r
388 returnValue = E_NOT_OK;
\r
391 return (returnValue);
\r
394 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)
\r
396 Std_ReturnType returnValue;
\r
398 /* Check for development errors. */
\r
399 if (E_OK == Adc_CheckSetupResultBuffer (group))
\r
401 AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;
\r
402 returnValue = E_OK;
\r
406 /* An error have been raised from Adc_CheckSetupResultBuffer(). */
\r
407 returnValue = E_NOT_OK;
\r
410 return (returnValue);
\r
413 #if (ADC_READ_GROUP_API == STD_ON)
\r
414 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)
\r
416 Std_ReturnType returnValue;
\r
417 Adc_ChannelType channel;
\r
419 if (E_OK == Adc_CheckReadGroup (group))
\r
421 if ((ADC_CONV_MODE_CONTINOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&
\r
422 ((ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||
\r
423 (ADC_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))
\r
425 /* ADC329, ADC331. */
\r
426 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
\r
427 returnValue = E_OK;
\r
429 else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&
\r
430 (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))
\r
433 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
435 returnValue = E_OK;
\r
440 returnValue = E_OK;
\r
443 if (E_OK == returnValue)
\r
445 /* Copy the result to application buffer. */
\r
446 for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)
\r
448 dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].resultBuffer[channel];
\r
454 /* An error have been raised from Adc_CheckReadGroup(). */
\r
455 returnValue = E_NOT_OK;
\r
458 return (returnValue);
\r
462 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)
\r
464 Adc_StatusType returnValue;
\r
465 if ((ADC_INIT == adcState) && (AdcConfigPtr != NULL))
\r
467 /* Adc initilised, OK to move on... */
\r
468 returnValue = AdcConfigPtr->groupConfigPtr[group].status->groupStatus;
\r
472 returnValue = ADC_IDLE;
\r
473 #if ( ADC_DEV_ERROR_DETECT == STD_ON )
\r
474 Det_ReportError(MODULE_ID_ADC,0,ADC_GETGROUPSTATUS_ID, ADC_E_UNINIT );
\r
478 return (returnValue);
\r
482 void Adc_Group0ConversionComplete (void)
\r
484 /* ISR for FIFO 0 end of queue. Clear interrupt flag. */
\r
485 EQADC.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;
\r
487 /* Sample completed. */
\r
488 AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->groupStatus = ADC_STREAM_COMPLETED;
\r
490 /* Call notification if enabled. */
\r
491 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
492 if (AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback != NULL)
\r
494 AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback();
\r
498 void Adc_Group1ConversionComplete (void)
\r
500 /* ISR for FIFO 0 end of queue. Clear interrupt flag. */
\r
501 EQADC.FISR[ADC_EQADC_QUEUE_1].B.EOQF = 1;
\r
503 /* Sample completed. */
\r
504 AdcConfigPtr->groupConfigPtr[ADC_GROUP1].status->groupStatus = ADC_STREAM_COMPLETED;
\r
506 /* Call notification if enabled. */
\r
507 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
508 if (AdcConfigPtr->groupConfigPtr[ADC_GROUP1].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP1].groupCallback != NULL)
\r
510 AdcConfigPtr->groupConfigPtr[ADC_GROUP1].groupCallback();
\r
515 void Adc_EQADCError (void)
\r
517 /* Something is wrong!! Check the cause of the error and try to correct it. */
\r
518 if (EQADC.FISR[ADC_EQADC_QUEUE_0].B.TORF)
\r
520 /* Trigger overrun on queue 0!! */
\r
523 else if (EQADC.FISR[ADC_EQADC_QUEUE_1].B.TORF)
\r
525 /* Trigger overrun on queue 1!! */
\r
528 else if (EQADC.FISR[ADC_EQADC_QUEUE_0].B.CFUF)
\r
530 /* Command underflow on queue 0!! */
\r
533 else if (EQADC.FISR[ADC_EQADC_QUEUE_1].B.CFUF)
\r
535 /* Command underflow on queue 1!! */
\r
538 else if (EQADC.FISR[ADC_EQADC_QUEUE_0].B.RFOF)
\r
540 /* Result overflow on queue 0!! */
\r
543 else if (EQADC.FISR[ADC_EQADC_QUEUE_1].B.RFOF)
\r
545 /* Result overflow on queue 1!! */
\r
550 /* Something else... TODO What have we missed above */
\r
555 /* Helper macro to make sure that the qommand queue have
\r
556 * executed the commands in the fifo.
\r
557 * First check that the H/W negate the
\r
558 * single scan bit and then wait for EOQ. */
\r
559 #define WAIT_FOR_QUEUE_TO_FINISH(q) \
\r
560 while (EQADC.FISR[q].B.SSS) \
\r
565 while (!EQADC.FISR[q].B.EOQF) \
\r
570 static void Adc_WriteEQADCRegister (Adc_EQADCRegisterType reg, Adc_EQADCRegister value)
\r
572 Adc_RegisterWriteType writeReg;
\r
573 uint32_t temp, oldMode;
\r
577 /* Write command. */
\r
579 writeReg.B.EOQ = 1;
\r
580 writeReg.B.ADC_REG = value;
\r
581 writeReg.B.ADC_REG_ADDR = reg;
\r
583 /* Invalidate queue. */
\r
584 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;
\r
587 /* Write command through FIFO. */
\r
588 EQADC.CFPR[ADC_EQADC_QUEUE_0].R = writeReg.R;
\r
591 oldMode = EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE;
\r
592 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_ONESHOT;
\r
593 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.SSE = 1;
\r
595 /* Wait for command to be executed. */
\r
596 WAIT_FOR_QUEUE_TO_FINISH(ADC_EQADC_QUEUE_0);
\r
598 /* Flush result buffer. */
\r
599 temp = EQADC.RFPR[ADC_EQADC_QUEUE_0].R;
\r
600 EQADC.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;
\r
602 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = oldMode;
\r
606 static Adc_EQADCRegister Adc_ReadEQADCRegister (Adc_EQADCRegisterType reg)
\r
608 Adc_RegisterReadType readReg;
\r
609 Adc_EQADCRegister result;
\r
610 uint32_t oldMode, dmaRequestEnable;
\r
614 /* Read command. */
\r
617 readReg.B.ADC_REG_ADDR = reg;
\r
618 readReg.B.MESSAGE_TAG = ADC_EQADC_QUEUE_0;
\r
620 /* Make sure that DMA requests for command fill and result drain is disabled. */
\r
621 if (EQADC.IDCR[ADC_EQADC_QUEUE_0].B.RFDE || EQADC.IDCR[ADC_EQADC_QUEUE_0].B.CFFE)
\r
623 EQADC.IDCR[ADC_EQADC_QUEUE_0].B.CFFE = 0;
\r
624 EQADC.IDCR[ADC_EQADC_QUEUE_0].B.RFDE = 0;
\r
626 /* Remember to enable requests again... */
\r
627 dmaRequestEnable = TRUE;
\r
631 dmaRequestEnable = FALSE;
\r
634 /* Invalidate queue. */
\r
635 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;
\r
637 /* Write command through FIFO. */
\r
638 EQADC.CFPR[ADC_EQADC_QUEUE_0].R = readReg.R;
\r
641 oldMode = EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE;
\r
642 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_ONESHOT;
\r
643 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.SSE = 1;
\r
645 /* Wait for command to be executed. */
\r
646 WAIT_FOR_QUEUE_TO_FINISH(ADC_EQADC_QUEUE_0);
\r
648 /* Read result buffer. */
\r
649 result = EQADC.RFPR[ADC_EQADC_QUEUE_0].R;
\r
650 EQADC.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;
\r
652 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = oldMode;
\r
654 if (dmaRequestEnable)
\r
656 EQADC.IDCR[ADC_EQADC_QUEUE_0].B.CFFE = 1;
\r
657 EQADC.IDCR[ADC_EQADC_QUEUE_0].B.RFDE = 1;
\r
666 #define SYSTEM_CLOCK_DIVIDE(f) ((f / 2) - 1)
\r
667 static void Adc_ConfigureEQADC (const Adc_ConfigType *ConfigPtr)
\r
669 Adc_GroupType group;
\r
673 ADC_ENABLE = 0x8000,
\r
676 Adc_WriteEQADCRegister (ADC0_CR, (ADC_ENABLE | ConfigPtr->hwConfigPtr->adcPrescale));
\r
678 /* Disable time stamp timer. */
\r
679 Adc_WriteEQADCRegister (ADC0_TSCR, 0);
\r
681 for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
\r
683 /* Enable eDMA requests for commands and results. */
\r
684 EQADC.IDCR[group].B.CFFS = 1;
\r
685 EQADC.IDCR[group].B.RFDS = 1;
\r
687 /* Invalidate FIFO. */
\r
688 EQADC.CFCR[group].B.CFINV = 1;
\r
690 /* Enable FIFO fill requests. */
\r
691 EQADC.IDCR[group].B.CFFE = 1;
\r
692 EQADC.IDCR[group].B.RFDE = 1;
\r
696 /* TODO How do we handle interrupt priorities? */
\r
697 #define EQADC_FIFO0_END_OF_QUEUE_PRIORITY (2)
\r
698 #define EQADC_FIFO1_END_OF_QUEUE_PRIORITY (2)
\r
699 #define EQADC_FISR_OVER_PRIORITY (2)
\r
701 void Adc_ConfigureEQADCInterrupts (void)
\r
703 Adc_GroupType group;
\r
705 #if defined(USE_KERNEL)
\r
707 tid = Os_Arc_CreateIsr(Adc_EQADCError,EQADC_FISR_OVER_PRIORITY,"Adc_Err");
\r
708 Irq_AttachIsr2(tid,NULL,EQADC_FISR_OVER);
\r
710 tid = Os_Arc_CreateIsr(Adc_Group0ConversionComplete,EQADC_FIFO0_END_OF_QUEUE_PRIORITY,"Adc_Grp0");
\r
711 Irq_AttachIsr2(tid,NULL,EQADC_FISR0_EOQF0);
\r
713 tid = Os_Arc_CreateIsr(Adc_Group1ConversionComplete,EQADC_FIFO1_END_OF_QUEUE_PRIORITY,"Adc_Grp1");
\r
714 Irq_AttachIsr2(tid,NULL,EQADC_FISR1_EOQF1);
\r
717 Irq_InstallVector (Adc_EQADCError,
\r
719 EQADC_FISR_OVER_PRIORITY, CPU_Z1);
\r
721 Irq_InstallVector (Adc_Group0ConversionComplete,
\r
723 EQADC_FIFO0_END_OF_QUEUE_PRIORITY, CPU_Z1);
\r
725 Irq_InstallVector (Adc_Group1ConversionComplete,
\r
727 EQADC_FIFO1_END_OF_QUEUE_PRIORITY, CPU_Z1);
\r
730 for (group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)
\r
732 /* Enable end of queue, queue overflow/underflow interrupts. Clear corresponding flags. */
\r
733 EQADC.FISR[group].B.RFOF = 1;
\r
734 EQADC.IDCR[group].B.RFOIE = 1;
\r
736 EQADC.FISR[group].B.CFUF = 1;
\r
737 EQADC.IDCR[group].B.CFUIE = 1;
\r
739 EQADC.FISR[group].B.TORF = 1;
\r
740 EQADC.IDCR[group].B.TORIE = 1;
\r
742 EQADC.FISR[group].B.EOQF = 1;
\r
743 EQADC.IDCR[group].B.EOQIE = 1;
\r
747 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)
\r
748 void Adc_StartGroupConversion (Adc_GroupType group)
\r
750 /* Run development error check. */
\r
751 if (E_OK == Adc_CheckStartGroupConversion (group))
\r
753 /* Set conversion mode. */
\r
754 EQADC.CFCR[group].B.MODE = AdcConfigPtr->groupConfigPtr[group].conversionMode;
\r
756 /* Set single scan enable bit if this group is one shot. */
\r
757 if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT)
\r
759 EQADC.CFCR[group].B.SSE = 1;
\r
761 /* Set group state to BUSY. */
\r
762 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
\r
767 /* Error have been set within Adc_CheckStartGroupConversion(). */
\r
774 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
775 void Adc_EnableGroupNotification (Adc_GroupType group)
\r
777 AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 1;
\r
780 void Adc_DisableGroupNotification (Adc_GroupType group)
\r
782 AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 0;
\r
786 static void Adc_EQADCCalibrationSequence (void)
\r
788 Adc_ValueGroupType calibrationResult[sizeof(AdcCalibrationCommandQueue)/sizeof(AdcCalibrationCommandQueue[0])];
\r
789 int32_t point25Average, point75Average, i;
\r
790 Adc_EQADCRegister tempGCC, tempOCC;
\r
793 IDEAL_RES25 = 0x1000,
\r
794 IDEAL_RES75 = 0x3000,
\r
797 /* Use group 0 DMA channel for calibration. */
\r
798 Dma_ConfigureChannel ((struct tcd_t *)&AdcCalibrationDMACommandConfig,DMA_ADC_GROUP0_COMMAND_CHANNEL);
\r
799 Dma_ConfigureChannelTranferSize (sizeof(AdcCalibrationCommandQueue)/sizeof(AdcCalibrationCommandQueue[0]),
\r
800 DMA_ADC_GROUP0_COMMAND_CHANNEL);
\r
801 Dma_ConfigureChannelSourceCorr (-sizeof(AdcCalibrationCommandQueue), DMA_ADC_GROUP0_COMMAND_CHANNEL);
\r
803 Dma_ConfigureChannel ((struct tcd_t *)&AdcCalibrationDMAResultConfig, DMA_ADC_GROUP0_RESULT_CHANNEL);
\r
804 Dma_ConfigureChannelTranferSize (sizeof(calibrationResult)/sizeof(calibrationResult[0]),
\r
805 DMA_ADC_GROUP0_RESULT_CHANNEL);
\r
806 Dma_ConfigureChannelDestinationCorr (-sizeof(calibrationResult), DMA_ADC_GROUP0_RESULT_CHANNEL);
\r
807 Dma_ConfigureDestinationAddress ((uint32_t)calibrationResult, DMA_ADC_GROUP0_RESULT_CHANNEL);
\r
809 /* Invalidate queues. */
\r
810 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;
\r
812 Dma_StartChannel (DMA_ADC_GROUP0_COMMAND_CHANNEL);
\r
813 Dma_StartChannel (DMA_ADC_GROUP0_RESULT_CHANNEL);
\r
815 /* Start conversion. */
\r
816 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_ONESHOT;
\r
817 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.SSE = 1;
\r
819 /* Wait for conversion to complete. */
\r
820 while(!Dma_ChannelDone (DMA_ADC_GROUP0_RESULT_CHANNEL))
\r
825 /* Stop DMA channels and write calibration data to ADC engine. */
\r
826 EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_DISABLED;
\r
827 Dma_StopChannel (DMA_ADC_GROUP0_COMMAND_CHANNEL);
\r
828 Dma_StopChannel (DMA_ADC_GROUP0_RESULT_CHANNEL);
\r
830 /* Calculate conversion factors and write to ADC. */
\r
831 point25Average = 0;
\r
832 point75Average = 0;
\r
833 for (i = 0; i < sizeof(calibrationResult)/sizeof(calibrationResult[0] / 2); i++)
\r
835 point25Average += calibrationResult[i];
\r
836 point75Average += calibrationResult[i + sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2];
\r
839 /* Calculate average and correction slope and offset. */
\r
840 point25Average /= (sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2);
\r
841 point75Average /= (sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2);
\r
843 tempGCC = ((IDEAL_RES75 - IDEAL_RES25) << 14) / (point75Average - point25Average);
\r
844 tempOCC = IDEAL_RES75 - ((tempGCC * point75Average) >> 14) - 2;
\r
846 /* GCC field is only 15 bits. */
\r
847 tempGCC = tempGCC & ~(1 << 15);
\r
849 /* OCC field is only 14 bits. */
\r
850 tempOCC = tempOCC & ~(3 << 14);
\r
852 /* Write calibration data to ADC engine. */
\r
853 Adc_WriteEQADCRegister (ADC0_GCCR, tempGCC);
\r
854 Adc_WriteEQADCRegister (ADC0_OCCR, tempOCC);
\r
856 /* Read back and check calibration values. */
\r
857 if (Adc_ReadEQADCRegister (ADC0_GCCR) != tempGCC)
\r
861 else if (Adc_ReadEQADCRegister (ADC0_OCCR) != tempOCC)
\r
867 /* Development error checking functions. */
\r
868 #if (ADC_READ_GROUP_API == STD_ON)
\r
869 static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group)
\r
871 Std_ReturnType returnValue;
\r
873 #if ( ADC_DEV_ERROR_DETECT == STD_ON )
\r
875 if (ADC_UNINIT == adcState)
\r
878 returnValue = E_NOT_OK;
\r
879 Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_UNINIT );
\r
881 else if ((group < ADC_GROUP0) || (group >= AdcConfigPtr->nbrOfGroups))
\r
884 returnValue = E_NOT_OK;
\r
885 Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_PARAM_GROUP );
\r
887 else if (ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)
\r
890 returnValue = E_NOT_OK;
\r
891 Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_IDLE );
\r
895 /* Nothing strange. Go on... */
\r
896 returnValue = E_OK;
\r
899 returnValue = E_OK;
\r
901 return (returnValue);
\r
905 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)
\r
906 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group)
\r
908 Std_ReturnType returnValue;
\r
909 #if ( ADC_DEV_ERROR_DETECT == STD_ON )
\r
910 if (!(ADC_INIT == adcState))
\r
912 /* ADC not initialised, ADC294. */
\r
913 Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_UNINIT );
\r
914 returnValue = E_NOT_OK;
\r
916 else if (!((group >= 0) && (group < AdcConfig->nbrOfGroups)))
\r
918 /* Wrong group ID, ADC125 */
\r
919 Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_PARAM_GROUP );
\r
920 returnValue = E_NOT_OK;
\r
922 else if (!(ADC_TRIGG_SRC_SW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))
\r
924 /* Wrong trig source, ADC133. */
\r
925 Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_WRONG_TRIGG_SRC);
\r
926 returnValue = E_NOT_OK;
\r
928 else if (!((ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||
\r
929 (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))
\r
931 /* Group status not OK, ADC351, ADC428 */
\r
932 Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_BUSY );
\r
936 * Sometimes the ADC-interrupt gets lost which means that the status is never reset to ADC_IDLE (done in Adc_ReadGroup).
\r
937 * Therefor another group conversion is never started...
\r
939 * The temporary fix is to always return E_OK here. But the reason for the bug needs to be investigated further.
\r
941 //returnValue = E_NOT_OK;
\r
942 returnValue = E_OK;
\r
946 returnValue = E_OK;
\r
949 returnValue = E_OK;
\r
951 return (returnValue);
\r
955 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr)
\r
957 Std_ReturnType returnValue;
\r
959 #if ( ADC_DEV_ERROR_DETECT == STD_ON )
\r
960 if (!(ADC_UNINIT == adcState))
\r
962 /* Oops, already initialised. */
\r
963 Det_ReportError(MODULE_ID_ADC,0,ADC_INIT_ID, ADC_E_ALREADY_INITIALIZED );
\r
964 returnValue = E_NOT_OK;
\r
966 else if (ConfigPtr == NULL)
\r
968 /* Wrong config! */
\r
969 Det_ReportError(MODULE_ID_ADC,0,ADC_INIT_ID, ADC_E_PARAM_CONFIG );
\r
970 returnValue = E_NOT_OK;
\r
975 returnValue = E_OK;
\r
978 returnValue = E_OK;
\r
980 return (returnValue);
\r
983 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group)
\r
985 Std_ReturnType returnValue;
\r
987 #if ( ADC_DEV_ERROR_DETECT == STD_ON )
\r
988 if (ADC_UNINIT == adcState)
\r
990 /* Driver not initialised. */
\r
991 Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_UNINIT );
\r
992 returnValue = E_NOT_OK;
\r
994 else if (group < AdcConfigPtr->nbrOfGroups)
\r
997 Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_PARAM_GROUP );
\r
998 returnValue = E_NOT_OK;
\r
1002 /* Looks good!! */
\r
1003 returnValue = E_OK;
\r
1006 returnValue = E_OK;
\r
1008 return (returnValue);
\r