]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Adc.c
35eae1053dd5fc800148a43297b921ccaafb2649
[arc.git] / arch / ppc / mpc55xx / drivers / Adc.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\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
9  *\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
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 \r
18 \r
19 \r
20 \r
21 \r
22 \r
23 #include <assert.h>\r
24 #include <stdlib.h>\r
25 //#include "System.h"\r
26 #include "mpc55xx.h"\r
27 #include "Modules.h"\r
28 #include "Mcu.h"\r
29 #include "Adc.h"\r
30 #include "Dma.h"\r
31 #include "Det.h"\r
32 #if defined(USE_KERNEL)\r
33 #include "Os.h"\r
34 #include "isr.h"\r
35 #include "arc.h"\r
36 #endif\r
37 \r
38 \r
39 typedef union\r
40 {\r
41   vuint32_t R;\r
42   struct\r
43   {\r
44     vuint32_t EOQ:1;\r
45     vuint32_t PAUSE:1;\r
46     vuint32_t :4;\r
47     vuint32_t BN:1;\r
48     vuint32_t RW:1;\r
49     vuint32_t ADC_REG:16;\r
50     vuint32_t ADC_REG_ADDR:8;\r
51    } B;\r
52 }Adc_RegisterWriteType;\r
53 \r
54 typedef union\r
55 {\r
56   vuint32_t R;\r
57   struct\r
58   {\r
59     vuint32_t EOQ:1;\r
60     vuint32_t PAUSE:1;\r
61     vuint32_t :4;\r
62     vuint32_t BN:1;\r
63     vuint32_t RW:1;\r
64     vuint32_t MESSAGE_TAG:4;\r
65     vuint32_t :12;\r
66     vuint32_t ADC_REG_ADDR:8;\r
67    } B;\r
68 }Adc_RegisterReadType;\r
69 \r
70 typedef enum\r
71 {\r
72   ADC_UNINIT,\r
73   ADC_INIT,\r
74 }Adc_StateType;\r
75 \r
76 typedef enum\r
77 {\r
78   ADC_EQADC_QUEUE_0,\r
79   ADC_EQADC_QUEUE_1,\r
80   ADC_EQADC_QUEUE_2,\r
81   ADC_EQADC_QUEUE_3,\r
82   ADC_EQADC_QUEUE_4,\r
83   ADC_EQADC_QUEUE_5,\r
84   ADC_EQADC_NBR_OF_QUEUES\r
85 }Adc_eQADCQueueType;\r
86 \r
87 typedef enum\r
88 {\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
93 \r
94 \r
95 typedef int16_t Adc_EQADCRegister;\r
96 \r
97 typedef enum\r
98 {\r
99   ADC0_CR = 1,\r
100   ADC0_TSCR,\r
101   ADC0_TBCR,\r
102   ADC0_GCCR,\r
103   ADC0_OCCR\r
104 }Adc_EQADCRegisterType;\r
105 \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
112 \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
118 \r
119 \r
120 static Adc_StateType adcState = ADC_UNINIT;\r
121 \r
122 /* Pointer to configuration structure. */\r
123 static const Adc_ConfigType *AdcConfigPtr;\r
124 \r
125 /* Command queue for calibration sequence. See 31.5.6 in reference manual. */\r
126 const Adc_CommandType AdcCalibrationCommandQueue [] =\r
127 {\r
128   /* Four samples of 25 % of (VRh - VRl). */\r
129   {\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
132   },\r
133   {\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
136   },\r
137   {\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
140   },\r
141   {\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
144   },\r
145   /* Four samples of 75 % of (VRh - VRl). */\r
146   {\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
149   },\r
150   {\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
153   },\r
154   {\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
157   },\r
158   {\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
161   }\r
162 };\r
163 \r
164 /* DMA configuration for calibration sequence. */\r
165 const struct tcd_t AdcCalibrationDMACommandConfig =\r
166 {\r
167   .SADDR = (uint32_t)AdcCalibrationCommandQueue,\r
168   .SMOD = 0,\r
169   .SSIZE = DMA_TRANSFER_SIZE_32BITS,\r
170   .DMOD = 0,\r
171   .DSIZE = DMA_TRANSFER_SIZE_32BITS,\r
172   .SOFF = sizeof(Adc_CommandType),\r
173   .NBYTES = sizeof(Adc_CommandType),\r
174   .SLAST = 0,\r
175   .DADDR = (vint32_t)&EQADC.CFPR[0].R,\r
176   .CITERE_LINK = 0,\r
177   .CITER = 0,\r
178   .DOFF = 0,\r
179   .DLAST_SGA = 0,\r
180   .BITERE_LINK = 0,\r
181   .BITER = 0,\r
182   .BWC = 0,\r
183   .MAJORLINKCH = 0,\r
184   .DONE = 0,\r
185   .ACTIVE = 0,\r
186   .MAJORE_LINK = 0,\r
187   .E_SG = 0,\r
188   .D_REQ = 0,\r
189   .INT_HALF = 0,\r
190   .INT_MAJ = 0,\r
191   .START = 0,\r
192 };\r
193 \r
194 const struct tcd_t AdcCalibrationDMAResultConfig =\r
195 {\r
196         .SADDR = (vint32_t)&EQADC.RFPR[0].R + 2,\r
197         .SMOD = 0,\r
198         .SSIZE = DMA_TRANSFER_SIZE_16BITS,\r
199         .DMOD = 0,\r
200         .DSIZE = DMA_TRANSFER_SIZE_16BITS,\r
201         .SOFF = 0,\r
202         .NBYTES = sizeof(Adc_ValueGroupType),\r
203         .SLAST = 0,\r
204         .DADDR = 0, /* Dynamic address, written later. */\r
205         .CITERE_LINK = 0,\r
206         .CITER = 0,\r
207         .DOFF = sizeof(Adc_ValueGroupType),\r
208         .DLAST_SGA = 0,\r
209         .BITERE_LINK = 0,\r
210         .BITER = 0,\r
211         .BWC = 0,\r
212         .MAJORLINKCH = 0,\r
213         .DONE = 0,\r
214         .ACTIVE = 0,\r
215         .MAJORE_LINK = 0,\r
216         .E_SG = 0,\r
217         .D_REQ = 0,\r
218         .INT_HALF = 0,\r
219         .INT_MAJ = 0,\r
220         .START = 0\r
221 };\r
222 \r
223 #if (ADC_DEINIT_API == STD_ON)\r
224 Std_ReturnType Adc_DeInit (const Adc_ConfigType *ConfigPtr)\r
225 {\r
226   Adc_eQADCQueueType queue;\r
227   Adc_GroupType group;\r
228   boolean queueStopped;\r
229 \r
230   if (ADC_UNINIT != adcState)\r
231   {\r
232     /* Stop all queues. */\r
233     for (queue = ADC_EQADC_QUEUE_0; queue < ADC_EQADC_NBR_OF_QUEUES; queue++)\r
234     {\r
235       /* Disable queue. */\r
236       EQADC.CFCR[queue].B.MODE = 0;\r
237 \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
242       {\r
243         switch (queue)\r
244         {\r
245         case ADC_EQADC_QUEUE_0:\r
246           queueStopped = (EQADC.CFSR.B.CFS0 == EQADC_CFIFO_STATUS_IDLE);\r
247           break;\r
248         case ADC_EQADC_QUEUE_1:\r
249           queueStopped = (EQADC.CFSR.B.CFS1 == EQADC_CFIFO_STATUS_IDLE);\r
250           break;\r
251         case ADC_EQADC_QUEUE_2:\r
252           queueStopped = (EQADC.CFSR.B.CFS2 == EQADC_CFIFO_STATUS_IDLE);\r
253           break;\r
254         case ADC_EQADC_QUEUE_3:\r
255           queueStopped = (EQADC.CFSR.B.CFS3 == EQADC_CFIFO_STATUS_IDLE);\r
256           break;\r
257         case ADC_EQADC_QUEUE_4:\r
258           queueStopped = (EQADC.CFSR.B.CFS4 == EQADC_CFIFO_STATUS_IDLE);\r
259           break;\r
260         case ADC_EQADC_QUEUE_5:\r
261           queueStopped = (EQADC.CFSR.B.CFS5 == EQADC_CFIFO_STATUS_IDLE);\r
262           break;\r
263         default :\r
264           /* We should never get here... Terminate loop. */\r
265           queueStopped = TRUE;\r
266           break;\r
267         }\r
268       }\r
269 \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
273 \r
274       /* Disable FIFO fill requests. */\r
275       EQADC.IDCR[queue].B.CFFE = 0;\r
276       EQADC.IDCR[queue].B.RFDE = 0;\r
277 \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
283     }\r
284 \r
285     /* Stop all DMA channels connected to EQADC. */\r
286     for (group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)\r
287     {\r
288       Dma_StopChannel (AdcConfigPtr->groupConfigPtr [group].dmaCommandChannel);\r
289       Dma_StopChannel (AdcConfigPtr->groupConfigPtr [group].dmaResultChannel);\r
290 \r
291       /* Set group status to idle. */\r
292       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
293     }\r
294 \r
295     /* Disable EQADC. */\r
296     Adc_WriteEQADCRegister (ADC0_CR, 0);\r
297 \r
298     /* Clean internal status. */\r
299     AdcConfigPtr = (Adc_ConfigType *)NULL;\r
300     adcState = ADC_UNINIT;\r
301   }\r
302   return (E_OK);\r
303 }\r
304 #endif\r
305 \r
306 Std_ReturnType Adc_Init (const Adc_ConfigType *ConfigPtr)\r
307 {\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
314 \r
315   if (E_OK == Adc_CheckInit(ConfigPtr))\r
316   {\r
317     /* First of all, store the location of the configuration data. */\r
318     AdcConfigPtr = ConfigPtr;\r
319 \r
320     /* Start configuring the eQADC queues. */\r
321     for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
322     {\r
323       /* Loop through all channels and make the command queue. */\r
324       for (channel = 0; channel < ConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
325       {\r
326         /* Get physical channel. */\r
327         channelId = ConfigPtr->groupConfigPtr[group].channelList[channel];\r
328 \r
329         commandQueue = ConfigPtr->groupConfigPtr[group].commandBuffer;\r
330 \r
331         /* Begin with empty command. */\r
332         command.R = 0;\r
333 \r
334         /* Physical channel number. */\r
335         command.B.CHANNEL_NUMBER = channelId;\r
336         /* Sample time. */\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
342 \r
343         /* Write command to command queue. */\r
344         commandQueue [channel].R = command.R;\r
345 \r
346         /* Last channel in group. Write EOQ and configure eQADC FIFO. */\r
347         if (channel == (ConfigPtr->groupConfigPtr[group].numberOfChannels - 1))\r
348         {\r
349           commandQueue [channel].B.EOQ = 1;\r
350         }\r
351       }\r
352     }\r
353 \r
354     /* Enable ADC. */\r
355     Adc_ConfigureEQADC (ConfigPtr);\r
356 \r
357     /* Perform calibration of the ADC. */\r
358     Adc_EQADCCalibrationSequence ();\r
359 \r
360     /* Configure DMA channels. */\r
361     for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
362     {\r
363       /* ADC307. */\r
364       ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
365 \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
368     }\r
369 \r
370     /* Start DMA channels. */\r
371     for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
372     {\r
373       /* Invalidate queues. */\r
374       EQADC.CFCR[group].B.CFINV = 1;\r
375 \r
376       Dma_StartChannel (ConfigPtr->groupConfigPtr [group].dmaResultChannel);\r
377       Dma_StartChannel (ConfigPtr->groupConfigPtr [group].dmaCommandChannel);\r
378     }\r
379 \r
380     Adc_ConfigureEQADCInterrupts ();\r
381 \r
382     /* Move on to INIT state. */\r
383     adcState = ADC_INIT;\r
384     returnValue = E_OK;\r
385   }\r
386   else\r
387   {\r
388     returnValue = E_NOT_OK;\r
389   }\r
390 \r
391   return (returnValue);\r
392 }\r
393 \r
394 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)\r
395 {\r
396   Std_ReturnType returnValue;\r
397 \r
398   /* Check for development errors. */\r
399   if (E_OK == Adc_CheckSetupResultBuffer (group))\r
400   {\r
401     AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;\r
402     returnValue = E_OK;\r
403   }\r
404   else\r
405   {\r
406     /* An error have been raised from Adc_CheckSetupResultBuffer(). */\r
407     returnValue = E_NOT_OK;\r
408   }\r
409 \r
410   return (returnValue);\r
411 }\r
412 \r
413 #if (ADC_READ_GROUP_API == STD_ON)\r
414 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)\r
415 {\r
416   Std_ReturnType returnValue;\r
417   Adc_ChannelType channel;\r
418 \r
419   if (E_OK == Adc_CheckReadGroup (group))\r
420   {\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
424     {\r
425       /* ADC329, ADC331. */\r
426       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
427       returnValue = E_OK;\r
428     }\r
429     else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
430              (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))\r
431     {\r
432       /* ADC330. */\r
433       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
434 \r
435       returnValue = E_OK;\r
436     }\r
437     else\r
438     {\r
439       /* Keep status. */\r
440       returnValue = E_OK;\r
441     }\r
442 \r
443     if (E_OK == returnValue)\r
444     {\r
445       /* Copy the result to application buffer. */\r
446       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
447       {\r
448         dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].resultBuffer[channel];\r
449       }\r
450     }\r
451   }\r
452   else\r
453   {\r
454     /* An error have been raised from Adc_CheckReadGroup(). */\r
455     returnValue = E_NOT_OK;\r
456   }\r
457 \r
458   return (returnValue);\r
459 }\r
460 #endif\r
461 \r
462 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)\r
463 {\r
464   Adc_StatusType returnValue;\r
465   if ((ADC_INIT == adcState) && (AdcConfigPtr != NULL))\r
466   {\r
467     /* Adc initilised, OK to move on... */\r
468     returnValue = AdcConfigPtr->groupConfigPtr[group].status->groupStatus;\r
469   }\r
470   else\r
471   {\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
475 #endif\r
476     }\r
477 \r
478   return (returnValue);\r
479 }\r
480 \r
481 \r
482 void Adc_Group0ConversionComplete (void)\r
483 {\r
484   /* ISR for FIFO 0 end of queue. Clear interrupt flag.  */\r
485   EQADC.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;\r
486 \r
487   /* Sample completed. */\r
488   AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->groupStatus = ADC_STREAM_COMPLETED;\r
489 \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
493   {\r
494     AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback();\r
495   }\r
496 #endif\r
497 }\r
498 void Adc_Group1ConversionComplete (void)\r
499 {\r
500   /* ISR for FIFO 0 end of queue. Clear interrupt flag.  */\r
501   EQADC.FISR[ADC_EQADC_QUEUE_1].B.EOQF = 1;\r
502 \r
503   /* Sample completed. */\r
504   AdcConfigPtr->groupConfigPtr[ADC_GROUP1].status->groupStatus = ADC_STREAM_COMPLETED;\r
505 \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
509   {\r
510           AdcConfigPtr->groupConfigPtr[ADC_GROUP1].groupCallback();\r
511   }\r
512 #endif\r
513 }\r
514 \r
515 void Adc_EQADCError (void)\r
516 {\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
519   {\r
520     /* Trigger overrun on queue 0!! */\r
521     assert (0);\r
522   }\r
523   else if (EQADC.FISR[ADC_EQADC_QUEUE_1].B.TORF)\r
524   {\r
525     /* Trigger overrun on queue 1!! */\r
526     assert (0);\r
527   }\r
528   else if (EQADC.FISR[ADC_EQADC_QUEUE_0].B.CFUF)\r
529   {\r
530     /* Command underflow on queue 0!! */\r
531     assert (0);\r
532   }\r
533   else if (EQADC.FISR[ADC_EQADC_QUEUE_1].B.CFUF)\r
534   {\r
535     /* Command underflow on queue 1!! */\r
536     assert (0);\r
537   }\r
538   else if (EQADC.FISR[ADC_EQADC_QUEUE_0].B.RFOF)\r
539   {\r
540     /* Result overflow on queue 0!! */\r
541     assert (0);\r
542   }\r
543   else if (EQADC.FISR[ADC_EQADC_QUEUE_1].B.RFOF)\r
544   {\r
545     /* Result overflow on queue 1!! */\r
546     assert (0);\r
547   }\r
548   else\r
549   {\r
550     /* Something else... TODO What have we missed above */\r
551     assert(0);\r
552   }\r
553 }\r
554 \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
561   {                                       \\r
562     ;                                     \\r
563   }                                       \\r
564                                           \\r
565   while (!EQADC.FISR[q].B.EOQF)           \\r
566   {                                       \\r
567     ;                                     \\r
568   }\r
569 \r
570 static void Adc_WriteEQADCRegister (Adc_EQADCRegisterType reg, Adc_EQADCRegister value)\r
571 {\r
572   Adc_RegisterWriteType writeReg;\r
573   uint32_t temp, oldMode;\r
574 \r
575   writeReg.R = 0;\r
576 \r
577   /* Write command. */\r
578   writeReg.B.RW = 0;\r
579   writeReg.B.EOQ = 1;\r
580   writeReg.B.ADC_REG = value;\r
581   writeReg.B.ADC_REG_ADDR = reg;\r
582 \r
583   /* Invalidate queue. */\r
584   EQADC.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;\r
585 \r
586 \r
587   /* Write command through FIFO. */\r
588   EQADC.CFPR[ADC_EQADC_QUEUE_0].R = writeReg.R;\r
589 \r
590   /* Enable FIFO. */\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
594 \r
595   /* Wait for command to be executed. */\r
596   WAIT_FOR_QUEUE_TO_FINISH(ADC_EQADC_QUEUE_0);\r
597 \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
601 \r
602   EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = oldMode;\r
603 \r
604 }\r
605 \r
606 static Adc_EQADCRegister Adc_ReadEQADCRegister (Adc_EQADCRegisterType reg)\r
607 {\r
608   Adc_RegisterReadType readReg;\r
609   Adc_EQADCRegister result;\r
610   uint32_t oldMode, dmaRequestEnable;\r
611 \r
612   readReg.R = 0;\r
613 \r
614   /* Read command. */\r
615   readReg.B.RW = 1;\r
616   readReg.B.EOQ = 1;\r
617   readReg.B.ADC_REG_ADDR = reg;\r
618   readReg.B.MESSAGE_TAG = ADC_EQADC_QUEUE_0;\r
619 \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
622   {\r
623     EQADC.IDCR[ADC_EQADC_QUEUE_0].B.CFFE = 0;\r
624     EQADC.IDCR[ADC_EQADC_QUEUE_0].B.RFDE = 0;\r
625 \r
626     /* Remember to enable requests again... */\r
627     dmaRequestEnable = TRUE;\r
628   }\r
629   else\r
630   {\r
631     dmaRequestEnable = FALSE;\r
632   }\r
633 \r
634   /* Invalidate queue. */\r
635   EQADC.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;\r
636 \r
637   /* Write command through FIFO. */\r
638   EQADC.CFPR[ADC_EQADC_QUEUE_0].R = readReg.R;\r
639 \r
640   /* Enable FIFO. */\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
644 \r
645   /* Wait for command to be executed. */\r
646   WAIT_FOR_QUEUE_TO_FINISH(ADC_EQADC_QUEUE_0);\r
647 \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
651 \r
652   EQADC.CFCR[ADC_EQADC_QUEUE_0].B.MODE = oldMode;\r
653 \r
654   if (dmaRequestEnable)\r
655   {\r
656     EQADC.IDCR[ADC_EQADC_QUEUE_0].B.CFFE = 1;\r
657     EQADC.IDCR[ADC_EQADC_QUEUE_0].B.RFDE = 1;\r
658   }\r
659   else\r
660   {\r
661     /* Do nothing. */\r
662   }\r
663   return (result);\r
664 }\r
665 \r
666 #define SYSTEM_CLOCK_DIVIDE(f)    ((f / 2) - 1)\r
667 static void  Adc_ConfigureEQADC (const Adc_ConfigType *ConfigPtr)\r
668 {\r
669   Adc_GroupType group;\r
670 \r
671   enum\r
672   {\r
673     ADC_ENABLE = 0x8000,\r
674   };\r
675   /* Enable ADC0. */\r
676   Adc_WriteEQADCRegister (ADC0_CR, (ADC_ENABLE | ConfigPtr->hwConfigPtr->adcPrescale));\r
677 \r
678   /* Disable time stamp timer. */\r
679   Adc_WriteEQADCRegister (ADC0_TSCR, 0);\r
680 \r
681   for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
682   {\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
686 \r
687     /* Invalidate FIFO. */\r
688     EQADC.CFCR[group].B.CFINV = 1;\r
689 \r
690     /* Enable FIFO fill requests. */\r
691     EQADC.IDCR[group].B.CFFE = 1;\r
692     EQADC.IDCR[group].B.RFDE = 1;\r
693   }\r
694 }\r
695 \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
700 \r
701 void Adc_ConfigureEQADCInterrupts (void)\r
702 {\r
703   Adc_GroupType group;\r
704 \r
705 #if defined(USE_KERNEL)\r
706   TaskType tid;\r
707   tid = Os_Arc_CreateIsr(Adc_EQADCError,EQADC_FISR_OVER_PRIORITY,"Adc_Err");\r
708   Irq_AttachIsr2(tid,NULL,EQADC_FISR_OVER);\r
709 \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
712 \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
715 \r
716 #else\r
717   Irq_InstallVector (Adc_EQADCError,\r
718                             EQADC_FISR_OVER,\r
719                             EQADC_FISR_OVER_PRIORITY, CPU_Z1);\r
720 \r
721   Irq_InstallVector (Adc_Group0ConversionComplete,\r
722                           EQADC_FISR0_EOQF0,\r
723                           EQADC_FIFO0_END_OF_QUEUE_PRIORITY, CPU_Z1);\r
724 \r
725   Irq_InstallVector (Adc_Group1ConversionComplete,\r
726                           EQADC_FISR1_EOQF1,\r
727                           EQADC_FIFO1_END_OF_QUEUE_PRIORITY, CPU_Z1);\r
728 \r
729 #endif\r
730   for (group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)\r
731   {\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
735 \r
736     EQADC.FISR[group].B.CFUF = 1;\r
737     EQADC.IDCR[group].B.CFUIE = 1;\r
738 \r
739     EQADC.FISR[group].B.TORF = 1;\r
740     EQADC.IDCR[group].B.TORIE = 1;\r
741 \r
742     EQADC.FISR[group].B.EOQF = 1;\r
743     EQADC.IDCR[group].B.EOQIE = 1;\r
744   }\r
745 }\r
746 \r
747 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
748 void Adc_StartGroupConversion (Adc_GroupType group)\r
749 {\r
750   /* Run development error check. */\r
751   if (E_OK == Adc_CheckStartGroupConversion (group))\r
752   {\r
753     /* Set conversion mode. */\r
754     EQADC.CFCR[group].B.MODE = AdcConfigPtr->groupConfigPtr[group].conversionMode;\r
755 \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
758     {\r
759       EQADC.CFCR[group].B.SSE = 1;\r
760 \r
761       /* Set group state to BUSY. */\r
762       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
763     }\r
764   }\r
765   else\r
766   {\r
767     /* Error have been set within Adc_CheckStartGroupConversion(). */\r
768   }\r
769 }\r
770 \r
771 \r
772 #endif\r
773 \r
774 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
775 void Adc_EnableGroupNotification (Adc_GroupType group)\r
776 {\r
777         AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 1;\r
778 }\r
779 \r
780 void Adc_DisableGroupNotification (Adc_GroupType group)\r
781 {\r
782         AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 0;\r
783 }\r
784 #endif\r
785 \r
786 static void Adc_EQADCCalibrationSequence (void)\r
787 {\r
788   Adc_ValueGroupType calibrationResult[sizeof(AdcCalibrationCommandQueue)/sizeof(AdcCalibrationCommandQueue[0])];\r
789   int32_t point25Average, point75Average, i;\r
790   Adc_EQADCRegister tempGCC, tempOCC;\r
791   enum\r
792   {\r
793     IDEAL_RES25 = 0x1000,\r
794     IDEAL_RES75 = 0x3000,\r
795   };\r
796 \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
802 \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
808 \r
809   /* Invalidate queues. */\r
810   EQADC.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;\r
811 \r
812   Dma_StartChannel (DMA_ADC_GROUP0_COMMAND_CHANNEL);\r
813   Dma_StartChannel (DMA_ADC_GROUP0_RESULT_CHANNEL);\r
814 \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
818 \r
819   /* Wait for conversion to complete. */\r
820   while(!Dma_ChannelDone (DMA_ADC_GROUP0_RESULT_CHANNEL))\r
821   {\r
822     ;\r
823   }\r
824 \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
829 \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
834   {\r
835     point25Average += calibrationResult[i];\r
836     point75Average += calibrationResult[i + sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2];\r
837   }\r
838 \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
842 \r
843   tempGCC = ((IDEAL_RES75 - IDEAL_RES25) << 14) / (point75Average - point25Average);\r
844   tempOCC = IDEAL_RES75 - ((tempGCC * point75Average) >> 14) - 2;\r
845 \r
846   /* GCC field is only 15 bits. */\r
847   tempGCC = tempGCC & ~(1 << 15);\r
848 \r
849   /* OCC field is only 14 bits. */\r
850   tempOCC = tempOCC & ~(3 << 14);\r
851 \r
852   /* Write calibration data to ADC engine. */\r
853   Adc_WriteEQADCRegister (ADC0_GCCR, tempGCC);\r
854   Adc_WriteEQADCRegister (ADC0_OCCR, tempOCC);\r
855 \r
856   /* Read back and check calibration values. */\r
857   if (Adc_ReadEQADCRegister (ADC0_GCCR) != tempGCC)\r
858   {\r
859     assert (0);\r
860   }\r
861   else if (Adc_ReadEQADCRegister (ADC0_OCCR) != tempOCC)\r
862   {\r
863     assert (0);\r
864   }\r
865 }\r
866 \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
870 {\r
871   Std_ReturnType returnValue;\r
872 \r
873 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
874 \r
875   if (ADC_UNINIT == adcState)\r
876   {\r
877     /* ADC296. */\r
878     returnValue = E_NOT_OK;\r
879     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_UNINIT );\r
880   }\r
881   else if ((group < ADC_GROUP0) || (group >= AdcConfigPtr->nbrOfGroups))\r
882   {\r
883     /* ADC152. */\r
884     returnValue = E_NOT_OK;\r
885     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_PARAM_GROUP );\r
886   }\r
887   else if (ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)\r
888   {\r
889     /* ADC388. */\r
890     returnValue = E_NOT_OK;\r
891     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_IDLE );\r
892   }\r
893   else\r
894   {\r
895     /* Nothing strange. Go on... */\r
896     returnValue = E_OK;\r
897   }\r
898 #else\r
899   returnValue = E_OK;\r
900 #endif\r
901   return (returnValue);\r
902 }\r
903 #endif\r
904 \r
905 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
906 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group)\r
907 {\r
908   Std_ReturnType returnValue;\r
909 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
910   if (!(ADC_INIT == adcState))\r
911   {\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
915   }\r
916   else  if (!((group >= 0) && (group < AdcConfig->nbrOfGroups)))\r
917   {\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
921   }\r
922   else if (!(ADC_TRIGG_SRC_SW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))\r
923   {\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
927   }\r
928   else if (!((ADC_IDLE             == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
929              (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
930   {\r
931     /* Group status not OK, ADC351, ADC428 */\r
932     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_BUSY );\r
933 \r
934     /*\r
935      * This is a BUG!\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
938      *\r
939      * The temporary fix is to always return E_OK here. But the reason for the bug needs to be investigated further.\r
940      */\r
941     //returnValue = E_NOT_OK;\r
942     returnValue = E_OK;\r
943   }\r
944   else\r
945   {\r
946     returnValue = E_OK;\r
947   }\r
948 #else\r
949   returnValue = E_OK;\r
950 #endif\r
951   return (returnValue);\r
952 }\r
953 #endif\r
954 \r
955 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr)\r
956 {\r
957   Std_ReturnType returnValue;\r
958 \r
959 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
960   if (!(ADC_UNINIT == adcState))\r
961   {\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
965   }\r
966   else if (ConfigPtr == NULL)\r
967   {\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
971   }\r
972   else\r
973   {\r
974     /* Looks good!! */\r
975     returnValue = E_OK;\r
976   }\r
977 #else\r
978     returnValue = E_OK;\r
979 #endif\r
980   return (returnValue);\r
981 }\r
982 \r
983 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group)\r
984 {\r
985   Std_ReturnType returnValue;\r
986 \r
987 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
988   if (ADC_UNINIT == adcState)\r
989   {\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
993   }\r
994   else if (group < AdcConfigPtr->nbrOfGroups)\r
995   {\r
996     /* ADC423 */\r
997     Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_PARAM_GROUP );\r
998     returnValue = E_NOT_OK;\r
999   }\r
1000   else\r
1001   {\r
1002     /* Looks good!! */\r
1003     returnValue = E_OK;\r
1004   }\r
1005 #else\r
1006   returnValue = E_OK;\r
1007 #endif\r
1008   return (returnValue);\r
1009 }\r
1010 \r
1011 \r