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
18 //#include "System.h"
\r
19 #include "mpc55xx.h"
\r
20 #include "Modules.h"
\r
28 #include "Adc_Internal.h"
\r
30 /* Uncomment and use DMA for 5606 only if you now what you are doing */
\r
31 #define DONT_USE_DMA_IN_ADC_MPC560X
\r
33 /* Are we gonna use Dma? */
\r
34 #if ( defined(CFG_MPC5606S) && !defined(DONT_USE_DMA_IN_ADC_MPC560X) )
\r
35 #define ADC_USES_DMA
\r
39 #if ( defined(ADC_USES_DMA) && !defined(USE_DMA) )
\r
40 #error Adc is configured to use Dma but the module is not enabled.
\r
43 #define ADC_GROUP0 0
\r
45 /* Function prototypes. */
\r
46 static void Adc_ConfigureADC (const Adc_ConfigType *ConfigPtr);
\r
47 static void Adc_ConfigureADCInterrupts (void);
\r
49 void Adc_GroupConversionComplete (Adc_GroupType group);
\r
51 /* static variable declarations */
\r
52 static Adc_StateType adcState = ADC_UNINIT;
\r
53 static const Adc_ConfigType *AdcConfigPtr; /* Pointer to configuration structure. */
\r
56 #if (ADC_DEINIT_API == STD_ON)
\r
57 Std_ReturnType Adc_DeInit (const Adc_ConfigType *ConfigPtr)
\r
61 if (E_OK == Adc_CheckDeInit(adcState, ConfigPtr))
\r
63 for(Adc_GroupType group = (Adc_GroupType)ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)
\r
65 /* Set group status to idle. */
\r
66 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
69 /* Disable DMA transfer*/
\r
70 #ifndef CFG_MPC5604B
\r
71 ADC_0.DMAE.B.DMAEN = 0;
\r
73 /* Power down ADC */
\r
74 ADC_0.MCR.R = 0x0001;
\r
76 /* Disable all interrupt*/
\r
79 /* Clean internal status. */
\r
80 AdcConfigPtr = (Adc_ConfigType *)NULL;
\r
81 adcState = ADC_UNINIT;
\r
88 Std_ReturnType Adc_Init (const Adc_ConfigType *ConfigPtr)
\r
90 if (E_OK == Adc_CheckInit(adcState, ConfigPtr))
\r
92 /* First of all, store the location of the configuration data. */
\r
93 AdcConfigPtr = ConfigPtr;
\r
96 Adc_ConfigureADC(ConfigPtr);
\r
98 Adc_ConfigureADCInterrupts();
\r
100 /* Move on to INIT state. */
\r
101 adcState = ADC_INIT;
\r
110 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)
\r
112 Std_ReturnType returnValue = E_NOT_OK;
\r
114 /* Check for development errors. */
\r
115 if (E_OK == Adc_CheckSetupResultBuffer (AdcConfigPtr, group))
\r
117 AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;
\r
119 returnValue = E_OK;
\r
122 return (returnValue);
\r
125 Adc_StreamNumSampleType Adc_GetStreamLastPointer(Adc_GroupType group, Adc_ValueGroupType** PtrToSamplePtr)
\r
127 Adc_StreamNumSampleType nofSample = 0;
\r
128 Adc_GroupDefType *groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[group];
\r
131 /* Check for development errors. */
\r
132 if ( (E_OK == Adc_CheckGetStreamLastPointer (adcState, AdcConfigPtr, group)) &&
\r
133 (groupPtr->status->groupStatus != ADC_BUSY) )
\r
135 /* Set resultPtr to application buffer. */
\r
136 if(groupPtr->status->currSampleCount > 0){
\r
137 *PtrToSamplePtr = &groupPtr->status->resultBufferPtr[groupPtr->status->currSampleCount-1];
\r
140 if ((ADC_CONV_MODE_ONESHOT == groupPtr->conversionMode) &&
\r
141 (ADC_STREAM_COMPLETED == groupPtr->status->groupStatus))
\r
143 /** @req ADC327. */
\r
144 groupPtr->status->groupStatus = ADC_IDLE;
\r
146 else if ((ADC_CONV_MODE_CONTINOUS == groupPtr->conversionMode) &&
\r
147 (ADC_ACCESS_MODE_STREAMING == groupPtr->accessMode) &&
\r
148 (ADC_STREAM_BUFFER_LINEAR == groupPtr->streamBufferMode) &&
\r
149 (ADC_STREAM_COMPLETED == groupPtr->status->groupStatus))
\r
151 /** @req ADC327. */
\r
152 groupPtr->status->groupStatus = ADC_IDLE;
\r
154 else if ( (ADC_CONV_MODE_CONTINOUS == groupPtr->conversionMode) &&
\r
155 ((ADC_STREAM_COMPLETED == groupPtr->status->groupStatus) ||
\r
156 (ADC_COMPLETED == groupPtr->status->groupStatus)) )
\r
158 /* Restart continous mode, and reset result buffer */
\r
159 if ((ADC_CONV_MODE_CONTINOUS == groupPtr->conversionMode) &&
\r
160 (ADC_STREAM_COMPLETED == groupPtr->status->groupStatus))
\r
162 /* Start continous conversion again */
\r
163 Adc_StartGroupConversion(group);
\r
168 else{/* Keep status. */}
\r
172 /* Some condition not met */
\r
173 *PtrToSamplePtr = NULL;
\r
180 #if (ADC_READ_GROUP_API == STD_ON)
\r
181 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)
\r
183 Std_ReturnType returnValue = E_OK;
\r
185 Adc_GroupDefType *groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[group];
\r
187 if (E_OK == Adc_CheckReadGroup (adcState, AdcConfigPtr, group))
\r
189 /* Copy the result to application buffer. */
\r
190 for (channel = 0; channel < groupPtr->numberOfChannels; channel++)
\r
192 if(groupPtr->status->currSampleCount > 0){
\r
193 dataBufferPtr[channel] = (&(groupPtr->status->resultBufferPtr[groupPtr->status->currSampleCount-1]))[channel];
\r
195 dataBufferPtr[channel] = groupPtr->status->resultBufferPtr[channel];
\r
199 if ((ADC_CONV_MODE_ONESHOT == groupPtr->conversionMode) &&
\r
200 (ADC_STREAM_COMPLETED == groupPtr->status->groupStatus))
\r
202 /** @req ADC330. */
\r
203 groupPtr->status->groupStatus = ADC_IDLE;
\r
205 else if ((ADC_CONV_MODE_CONTINOUS == groupPtr->conversionMode) &&
\r
206 (ADC_STREAM_BUFFER_LINEAR == groupPtr->streamBufferMode) &&
\r
207 (ADC_ACCESS_MODE_STREAMING == groupPtr->accessMode) &&
\r
208 (ADC_STREAM_COMPLETED == groupPtr->status->groupStatus))
\r
210 /** @req ADC330. */
\r
211 groupPtr->status->groupStatus = ADC_IDLE;
\r
213 else if ((ADC_CONV_MODE_CONTINOUS == groupPtr->conversionMode) &&
\r
214 ((ADC_STREAM_COMPLETED == groupPtr->status->groupStatus) ||
\r
215 (ADC_COMPLETED == groupPtr->status->groupStatus)))
\r
218 /* Restart continous mode, and reset result buffer */
\r
219 if ((ADC_CONV_MODE_CONTINOUS == groupPtr->conversionMode) &&
\r
220 (ADC_STREAM_COMPLETED == groupPtr->status->groupStatus))
\r
222 /* Start continous conversion again */
\r
223 Adc_StartGroupConversion(group);
\r
228 else{/* Keep status. */}
\r
232 /* An error have been raised from Adc_CheckReadGroup(). */
\r
233 returnValue = E_NOT_OK;
\r
236 return (returnValue);
\r
240 void Adc_GroupConversionComplete (Adc_GroupType group)
\r
242 Adc_GroupDefType *adcGroup = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[group];
\r
244 if(ADC_ACCESS_MODE_SINGLE == adcGroup->accessMode )
\r
246 adcGroup->status->groupStatus = ADC_STREAM_COMPLETED;
\r
247 /* Call notification if enabled. */
\r
248 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
249 if (adcGroup->status->notifictionEnable && adcGroup->groupCallback != NULL)
\r
251 adcGroup->groupCallback();
\r
254 /* Disable trigger normal conversions for ADC0 */
\r
255 ADC_0.MCR.B.NSTART=0;
\r
259 if(ADC_STREAM_BUFFER_LINEAR == adcGroup->streamBufferMode)
\r
261 adcGroup->status->currSampleCount++;
\r
262 if(adcGroup->status->currSampleCount < adcGroup->streamNumSamples)
\r
264 adcGroup->status->currResultBufPtr += adcGroup->numberOfChannels;
\r
265 adcGroup->status->groupStatus = ADC_COMPLETED;
\r
267 #if defined (ADC_USES_DMA)
\r
268 /* Increase current result buffer ptr */
\r
269 Dma_ConfigureDestinationAddress((uint32_t)adcGroup->status->currResultBufPtr, adcGroup->dmaResultChannel);
\r
272 ADC_0.IMR.B.MSKECH = 1;
\r
273 ADC_0.MCR.B.NSTART=1;
\r
277 /* All sample completed. */
\r
278 adcGroup->status->groupStatus = ADC_STREAM_COMPLETED;
\r
280 /* Call notification if enabled. */
\r
281 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
282 if (adcGroup->status->notifictionEnable && adcGroup->groupCallback != NULL){
\r
283 adcGroup->groupCallback();
\r
286 /* Disable trigger normal conversions for ADC0 */
\r
287 ADC_0.MCR.B.NSTART=0;
\r
290 else if(ADC_STREAM_BUFFER_CIRCULAR == adcGroup->streamBufferMode)
\r
292 adcGroup->status->currSampleCount++;
\r
293 if(adcGroup->status->currSampleCount < adcGroup->streamNumSamples)
\r
295 adcGroup->status->currResultBufPtr += adcGroup->numberOfChannels;
\r
296 #if defined (ADC_USES_DMA)
\r
297 /* Increase current result buffer ptr */
\r
298 Dma_ConfigureDestinationAddress((uint32_t)adcGroup->status->currResultBufPtr, adcGroup->dmaResultChannel);
\r
300 adcGroup->status->groupStatus = ADC_COMPLETED;
\r
302 ADC_0.IMR.B.MSKECH = 1;
\r
303 ADC_0.MCR.B.NSTART=1;
\r
307 /* Sample completed. */
\r
308 /* Disable trigger normal conversions for ADC*/
\r
309 ADC_0.MCR.B.NSTART=0;
\r
310 adcGroup->status->groupStatus = ADC_STREAM_COMPLETED;
\r
311 /* Call notification if enabled. */
\r
312 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
313 if (adcGroup->status->notifictionEnable && adcGroup->groupCallback != NULL)
\r
315 adcGroup->groupCallback();
\r
326 void Adc_Group0ConversionComplete (void)
\r
328 /* Clear ECH Flag and disable interruput */
\r
329 ADC_0.ISR.B.ECH = 1;
\r
330 ADC_0.IMR.B.MSKECH = 0;
\r
332 // Check which group is busy, only one is allowed to be busy at a time in a hw unit
\r
333 for (int group = 0; group < ADC_NBR_OF_GROUPS; group++)
\r
335 if((AdcConfigPtr->groupConfigPtr[group].status->groupStatus == ADC_BUSY) ||
\r
336 (AdcConfigPtr->groupConfigPtr[group].status->groupStatus == ADC_COMPLETED))
\r
338 #if !defined (ADC_USES_DMA)
\r
339 /* Copy to result buffer */
\r
340 for(uint8 index=0; index < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; index++)
\r
342 #if defined(CFG_MPC5606S)
\r
343 AdcConfigPtr->groupConfigPtr[group].status->currResultBufPtr[index] = ADC_0.CDR[32+AdcConfigPtr->groupConfigPtr[group].channelList[index]].B.CDATA;
\r
345 AdcConfigPtr->groupConfigPtr[group].status->currResultBufPtr[index] = ADC_0.CDR[AdcConfigPtr->groupConfigPtr[group].channelList[index]].B.CDATA;
\r
350 Adc_GroupConversionComplete((Adc_GroupType)group);
\r
356 void Adc_WatchdogError (void){
\r
358 void Adc_ADCError (void){
\r
361 static void Adc_ConfigureADC (const Adc_ConfigType *ConfigPtr)
\r
363 /* Set ADC CLOCK */
\r
364 ADC_0.MCR.B.ADCLKSEL = ConfigPtr->hwConfigPtr->adcPrescale;
\r
366 ADC_0.DSDR.B.DSD = 254;
\r
369 ADC_0.MCR.B.PWDN = 0;
\r
371 #if defined(ADC_USES_DMA)
\r
373 ADC_0.DMAE.B.DMAEN = 1;
\r
377 void Adc_ConfigureADCInterrupts (void)
\r
379 ISR_INSTALL_ISR2( "Adc_Err", Adc_ADCError, ADC_ER_INT, 2, 0 );
\r
380 ISR_INSTALL_ISR2( "Adc_Grp", Adc_Group0ConversionComplete, ADC_EOC_INT, 2, 0 );
\r
381 ISR_INSTALL_ISR2( "Adc_Wdg", Adc_WatchdogError, ADC_WD_INT, 2, 0 );
\r
384 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)
\r
385 void Adc_StartGroupConversion (Adc_GroupType group)
\r
387 Adc_GroupDefType *groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[group];
\r
389 /* Run development error check. */
\r
390 if (E_OK == Adc_CheckStartGroupConversion (adcState, AdcConfigPtr, group))
\r
392 /* Disable trigger normal conversions for ADC0 */
\r
393 ADC_0.MCR.B.NSTART = 0;
\r
395 /* Set group state to BUSY. */
\r
396 groupPtr->status->groupStatus = ADC_BUSY;
\r
398 groupPtr->status->currSampleCount = 0;
\r
399 groupPtr->status->currResultBufPtr = groupPtr->status->resultBufferPtr; /* Set current result buffer */
\r
401 #if defined(ADC_USES_DMA)
\r
402 Dma_ConfigureChannel ((Dma_TcdType *)groupPtr->groupDMAResults, groupPtr->dmaResultChannel);
\r
403 Dma_ConfigureDestinationAddress ((uint32_t)groupPtr->status->currResultBufPtr, groupPtr->dmaResultChannel);
\r
405 /* Always use single shot in streaming mode */
\r
406 if( groupPtr->accessMode == ADC_ACCESS_MODE_STREAMING)
\r
408 /* Set conversion mode. */
\r
409 ADC_0.MCR.B.MODE = ADC_CONV_MODE_ONESHOT;
\r
413 /* Set conversion mode. */
\r
414 ADC_0.MCR.B.MODE = groupPtr->conversionMode;
\r
417 /* Enable Overwrite*/
\r
418 ADC_0.MCR.B.OWREN = 1;
\r
420 /* Set Conversion Time. */
\r
421 #if defined(CFG_MPC5606S)
\r
422 uint32 groupChannelIdMask = 0;
\r
424 ADC_0.CTR[1].B.INPLATCH = groupPtr->adcChannelConvTime.INPLATCH;
\r
425 ADC_0.CTR[1].B.INPCMP = groupPtr->adcChannelConvTime.INPCMP;
\r
426 ADC_0.CTR[1].B.INPSAMP = groupPtr->adcChannelConvTime.INPSAMP;
\r
428 for(uint8 i =0; i < groupPtr->numberOfChannels; i++)
\r
430 groupChannelIdMask |= (1 << groupPtr->channelList[i]);
\r
433 #if defined(ADC_USES_DMA)
\r
434 ADC_0.DMAE.R = 0x01;
\r
435 /* Enable DMA Transfer */
\r
436 ADC_0.DMAR[1].R = groupChannelIdMask;
\r
437 Dma_StartChannel(DMA_ADC_GROUP0_RESULT_CHANNEL); /* Enable EDMA channel for ADC */
\r
440 /* Enable Normal conversion */
\r
441 ADC_0.NCMR[1].R = groupChannelIdMask;
\r
443 /* Enable Channel Interrupt */
\r
444 ADC_0.CIMR[1].R = groupChannelIdMask;
\r
447 uint32 groupChannelIdMask[3] = {0,0,0};
\r
449 ADC_0.CTR[0].B.INPLATCH = groupPtr->adcChannelConvTime.INPLATCH;
\r
450 ADC_0.CTR[0].B.INPCMP = groupPtr->adcChannelConvTime.INPCMP;
\r
451 ADC_0.CTR[0].B.INPSAMP = groupPtr->adcChannelConvTime.INPSAMP;
\r
452 ADC_0.CTR[1].B.INPLATCH = groupPtr->adcChannelConvTime.INPLATCH;
\r
453 ADC_0.CTR[1].B.INPCMP = groupPtr->adcChannelConvTime.INPCMP;
\r
454 ADC_0.CTR[1].B.INPSAMP = groupPtr->adcChannelConvTime.INPSAMP;
\r
455 ADC_0.CTR[2].B.INPLATCH = groupPtr->adcChannelConvTime.INPLATCH;
\r
456 ADC_0.CTR[2].B.INPCMP = groupPtr->adcChannelConvTime.INPCMP;
\r
457 ADC_0.CTR[2].B.INPSAMP = groupPtr->adcChannelConvTime.INPSAMP;
\r
459 for(uint8 i =0; i < groupPtr->numberOfChannels; i++)
\r
461 if(groupPtr->channelList[i] <= 15){
\r
462 groupChannelIdMask[0] |= (1 << groupPtr->channelList[i]);
\r
463 }else if((groupPtr->channelList[i] >= 32) && (groupPtr->channelList[i] <=47)){
\r
464 groupChannelIdMask[1] |= (1 << (groupPtr->channelList[i] - 32));
\r
465 }else if((groupPtr->channelList[i] >= 64) && (groupPtr->channelList[i] <=95)){
\r
466 groupChannelIdMask[2] |= (1 << (groupPtr->channelList[i] - 64));
\r
470 /* Enable Normal conversion */
\r
471 ADC_0.NCMR[0].R = groupChannelIdMask[0];
\r
472 ADC_0.NCMR[1].R = groupChannelIdMask[1];
\r
473 ADC_0.NCMR[2].R = groupChannelIdMask[2];
\r
475 /* Enable Channel Interrupt */
\r
476 ADC_0.CIMR[0].R = groupChannelIdMask[0];
\r
477 ADC_0.CIMR[1].R = groupChannelIdMask[1];
\r
478 ADC_0.CIMR[2].R = groupChannelIdMask[2];
\r
480 /* Clear interrupts */
\r
481 ADC_0.ISR.B.ECH = 1;
\r
482 /* Enable ECH interrupt */
\r
483 ADC_0.IMR.B.MSKECH = 1;
\r
485 /* Trigger normal conversions for ADC0 */
\r
486 ADC_0.MCR.B.NSTART = 1;
\r
490 /* Error have been set within Adc_CheckStartGroupConversion(). */
\r
494 void Adc_StopGroupConversion (Adc_GroupType group)
\r
496 if (E_OK == Adc_CheckStopGroupConversion (adcState, AdcConfigPtr, group))
\r
498 /* Disable trigger normal conversions for ADC0 */
\r
499 ADC_0.MCR.B.NSTART = 0;
\r
501 /* Set group state to IDLE. */
\r
502 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
504 /* Disable group notification if enabled. */
\r
505 if(1 == AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable){
\r
506 Adc_DisableGroupNotification (group);
\r
511 /* Error have been set within Adc_CheckStartGroupConversion(). */
\r
514 #endif /* endof #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON) */
\r
516 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
517 void Adc_EnableGroupNotification (Adc_GroupType group)
\r
519 Adc_EnableInternalGroupNotification(adcState, AdcConfigPtr, group);
\r
522 void Adc_DisableGroupNotification (Adc_GroupType group)
\r
524 Adc_InternalDisableGroupNotification(adcState, AdcConfigPtr, group);
\r
528 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)
\r
530 return Adc_InternalGetGroupStatus(adcState, AdcConfigPtr, group);
\r