]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Adc.c
Cleanup of makefiles. Cleanup of merge.
[arc.git] / arch / arm / arm_cm3 / 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 #include <assert.h>\r
18 #include <stdlib.h>\r
19 //#include "System.h"\r
20 //#include "Modules.h"\r
21 #include "Mcu.h"\r
22 #include "Adc.h"\r
23 #include "stm32f10x_adc.h"\r
24 #include "stm32f10x_dma.h"\r
25 #include "Det.h"\r
26 #if defined(USE_KERNEL)\r
27 #include "Os.h"\r
28 #include "isr.h"\r
29 #endif\r
30 \r
31 \r
32 typedef enum\r
33 {\r
34   ADC_UNINIT,\r
35   ADC_INIT,\r
36 }Adc_StateType;\r
37 \r
38 /* Conversion result register for ADC1. */\r
39 #define ADC1_DR_Address    ((u32)0x4001244C)\r
40 \r
41 /* Function prototypes. */\r
42 \r
43 /* Development error checking. */\r
44 static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group);\r
45 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group);\r
46 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr);\r
47 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group);\r
48 \r
49 static void Adc_Group0ConversionComplete (void);\r
50 \r
51 \r
52 static Adc_StateType adcState = ADC_UNINIT;\r
53 \r
54 /* Pointer to configuration structure. */\r
55 static const Adc_ConfigType *AdcConfigPtr;\r
56 \r
57 \r
58 #if (ADC_DEINIT_API == STD_ON)\r
59 Std_ReturnType Adc_DeInit (const Adc_ConfigType *ConfigPtr)\r
60 {\r
61   DMA_DeInit(DMA1_Channel1);\r
62   ADC_DeInit(ADC1);\r
63 \r
64   return (E_OK);\r
65 }\r
66 #endif\r
67 \r
68 Std_ReturnType Adc_Init (const Adc_ConfigType *ConfigPtr)\r
69 {\r
70   Std_ReturnType returnValue;\r
71   Adc_ChannelType channel;\r
72   Adc_ChannelType channelId;\r
73   Adc_GroupType group;\r
74 \r
75   ADC_InitTypeDef ADC_InitStructure;\r
76   DMA_InitTypeDef DMA_InitStructure;\r
77 \r
78   ADC_TempSensorVrefintCmd(ENABLE);\r
79 \r
80   if (E_OK == Adc_CheckInit(ConfigPtr))\r
81   {\r
82     /* First of all, store the location of the configuration data. */\r
83     AdcConfigPtr = ConfigPtr;\r
84 \r
85     /* DMA1 channel1 configuration ---------------------------------------------*/\r
86     DMA_DeInit(DMA1_Channel1);\r
87     DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;\r
88     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ConfigPtr->groupConfigPtr->resultBuffer;\r
89     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;\r
90     DMA_InitStructure.DMA_BufferSize = ConfigPtr->groupConfigPtr->numberOfChannels;\r
91     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;\r
92     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;\r
93     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;\r
94     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;\r
95     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;\r
96     DMA_InitStructure.DMA_Priority = DMA_Priority_High;\r
97     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;\r
98     DMA_Init(DMA1_Channel1, &DMA_InitStructure);\r
99 \r
100       // Connect interrupt to correct isr\r
101         TaskType tid;\r
102         tid = Os_Arc_CreateIsr(Adc_Group0ConversionComplete,6/*prio*/,"DMA1");\r
103         Irq_AttachIsr2(tid,NULL, DMA1_Channel1_IRQn);\r
104 \r
105     /* Enable DMA1 channel1 */\r
106     DMA_Cmd(DMA1_Channel1, ENABLE);\r
107 \r
108     /* Enable the DMA1 Channel1 Transfer complete interrupt */\r
109     DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);\r
110 \r
111     /* ADC1 configuration ------------------------------------------------------*/\r
112     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;\r
113     ADC_InitStructure.ADC_ScanConvMode = ENABLE;\r
114     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;\r
115     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;\r
116     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;\r
117     ADC_InitStructure.ADC_NbrOfChannel = ConfigPtr->groupConfigPtr->numberOfChannels;\r
118     ADC_Init(ADC1, &ADC_InitStructure);\r
119 \r
120     /* Start configuring the channel queues. */\r
121     for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
122     {\r
123       /* Loop through all channels and make the command queue. */\r
124       for (channel = 0; channel < ConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
125       {\r
126         /* Get physical channel. */\r
127         channelId = ConfigPtr->groupConfigPtr[group].channelList[channel];\r
128 \r
129         /* Configure channel as regular. */\r
130         ADC_RegularChannelConfig(ADC1, channelId, channel+1,\r
131           ConfigPtr->channelConfigPtr [channel].adcChannelConvTime);\r
132 \r
133       }\r
134     }\r
135 \r
136     for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
137     {\r
138       /* ADC307. */\r
139       ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
140     }\r
141 \r
142     /* Enable ADC1 DMA */\r
143     ADC_DMACmd(ADC1, ENABLE);\r
144 \r
145     /* Enable ADC1 */\r
146     ADC_Cmd(ADC1, ENABLE);\r
147 \r
148     /* Enable ADC1 reset calibaration register */\r
149     ADC_ResetCalibration(ADC1);\r
150     /* Check the end of ADC1 reset calibration register */\r
151     while(ADC_GetResetCalibrationStatus(ADC1));\r
152 \r
153     /* Start ADC1 calibaration */\r
154     ADC_StartCalibration(ADC1);\r
155 \r
156     /* Check the end of ADC1 calibration */\r
157     while(ADC_GetCalibrationStatus(ADC1));\r
158 \r
159     /* Move on to INIT state. */\r
160     adcState = ADC_INIT;\r
161     returnValue = E_OK;\r
162   }\r
163   else\r
164   {\r
165     returnValue = E_NOT_OK;\r
166   }\r
167 \r
168   return (returnValue);\r
169 }\r
170 \r
171 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)\r
172 {\r
173   Std_ReturnType returnValue;\r
174 \r
175   /* Check for development errors. */\r
176   if (E_OK == Adc_CheckSetupResultBuffer (group))\r
177   {\r
178     AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;\r
179     returnValue = E_OK;\r
180   }\r
181   else\r
182   {\r
183     /* An error have been raised from Adc_CheckSetupResultBuffer(). */\r
184     returnValue = E_NOT_OK;\r
185   }\r
186 \r
187   return (returnValue);\r
188 }\r
189 \r
190 #if (ADC_READ_GROUP_API == STD_ON)\r
191 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)\r
192 {\r
193   Std_ReturnType returnValue;\r
194   Adc_ChannelType channel;\r
195 \r
196   if (E_OK == Adc_CheckReadGroup (group))\r
197   {\r
198     if ((ADC_CONV_MODE_CONTINUOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
199          ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
200           (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
201     {\r
202       /* ADC329, ADC331. */\r
203       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
204       returnValue = E_OK;\r
205     }\r
206     else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
207              (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))\r
208     {\r
209       /* ADC330. */\r
210       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
211 \r
212       returnValue = E_OK;\r
213     }\r
214     else\r
215     {\r
216       /* Keep status. */\r
217       returnValue = E_OK;\r
218     }\r
219 \r
220     if (E_OK == returnValue)\r
221     {\r
222       /* Copy the result to application buffer. */\r
223       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
224       {\r
225         dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].resultBuffer[channel];\r
226       }\r
227     }\r
228   }\r
229   else\r
230   {\r
231     /* An error have been raised from Adc_CheckReadGroup(). */\r
232     returnValue = E_NOT_OK;\r
233   }\r
234 \r
235   return (returnValue);\r
236 }\r
237 #endif\r
238 \r
239 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)\r
240 {\r
241   Adc_StatusType returnValue;\r
242   if ((ADC_INIT == adcState) && (AdcConfigPtr != NULL))\r
243   {\r
244     /* Adc initilised, OK to move on... */\r
245     returnValue = AdcConfigPtr->groupConfigPtr[group].status->groupStatus;\r
246   }\r
247   else\r
248   {\r
249     returnValue = ADC_IDLE;\r
250 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
251     Det_ReportError(MODULE_ID_ADC,0,ADC_GETGROUPSTATUS_ID, ADC_E_UNINIT );\r
252 #endif\r
253     }\r
254 \r
255   return (returnValue);\r
256 }\r
257 \r
258 \r
259 static void Adc_Group0ConversionComplete (void)\r
260 {\r
261   /* ISR for DMA. Clear interrupt flag.  */\r
262   DMA_ClearFlag(DMA1_FLAG_TC1);\r
263 \r
264   /* Sample completed. */\r
265   AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->groupStatus = ADC_STREAM_COMPLETED;\r
266 \r
267   /* Call notification if enabled. */\r
268 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
269   if (AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback != NULL)\r
270   {\r
271     AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback();\r
272   }\r
273 #endif\r
274 }\r
275 \r
276 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
277 void Adc_StartGroupConversion (Adc_GroupType group)\r
278 {\r
279   /* Run development error check. */\r
280   if (E_OK == Adc_CheckStartGroupConversion (group))\r
281   {\r
282     /* Set conversion mode. */\r
283     /* Only software trigged single scan supported. */\r
284 \r
285     /* Set single scan enable bit if this group is one shot. */\r
286     if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT)\r
287     {\r
288       ADC_SoftwareStartConvCmd(ADC1, ENABLE);\r
289       /* Set group state to BUSY. */\r
290       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
291     }\r
292   }\r
293   else\r
294   {\r
295     /* Error have been set within Adc_CheckStartGroupConversion(). */\r
296   }\r
297 }\r
298 \r
299 \r
300 #endif\r
301 \r
302 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
303 void Adc_EnableGroupNotification (Adc_GroupType group)\r
304 {\r
305         AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 1;\r
306 }\r
307 \r
308 void Adc_DisableGroupNotification (Adc_GroupType group)\r
309 {\r
310         AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 0;\r
311 }\r
312 #endif\r
313 \r
314 \r
315 /* Development error checking functions. */\r
316 #if (ADC_READ_GROUP_API == STD_ON)\r
317 static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group)\r
318 {\r
319   Std_ReturnType returnValue;\r
320 \r
321 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
322 \r
323   if (ADC_UNINIT == adcState)\r
324   {\r
325     /* ADC296. */\r
326     returnValue = E_NOT_OK;\r
327     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_UNINIT );\r
328   }\r
329   else if ((group < ADC_GROUP0) || (group >= AdcConfigPtr->nbrOfGroups))\r
330   {\r
331     /* ADC152. */\r
332     returnValue = E_NOT_OK;\r
333     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_PARAM_GROUP );\r
334   }\r
335   else if (ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)\r
336   {\r
337     /* ADC388. */\r
338     returnValue = E_NOT_OK;\r
339     Det_ReportError(MODULE_ID_ADC,0,ADC_READGROUP_ID ,ADC_E_IDLE );\r
340   }\r
341   else\r
342   {\r
343     /* Nothing strange. Go on... */\r
344     returnValue = E_OK;\r
345   }\r
346 #else\r
347   returnValue = E_OK;\r
348 #endif\r
349   return (returnValue);\r
350 }\r
351 #endif\r
352 \r
353 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
354 static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group)\r
355 {\r
356   Std_ReturnType returnValue;\r
357 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
358   if (!(ADC_INIT == adcState))\r
359   {\r
360     /* ADC not initialised, ADC294. */\r
361     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_UNINIT );\r
362     returnValue = E_NOT_OK;\r
363   }\r
364   else  if (!((group >= 0) && (group < AdcConfig->nbrOfGroups)))\r
365   {\r
366     /* Wrong group ID, ADC125 */\r
367     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_PARAM_GROUP );\r
368     returnValue = E_NOT_OK;\r
369   }\r
370   else if (!(ADC_TRIGG_SRC_SW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))\r
371   {\r
372     /* Wrong trig source, ADC133. */\r
373     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_WRONG_TRIGG_SRC);\r
374     returnValue = E_NOT_OK;\r
375   }\r
376   else if (!((ADC_IDLE             == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
377              (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
378   {\r
379     /* Group status not OK, ADC351, ADC428 */\r
380     Det_ReportError(MODULE_ID_ADC,0,ADC_STARTGROUPCONVERSION_ID, ADC_E_BUSY );\r
381 \r
382     /*\r
383      * This is a BUG!\r
384      * Sometimes the ADC-interrupt gets lost which means that the status is never reset to ADC_IDLE (done in Adc_ReadGroup).\r
385      * Therefor another group conversion is never started...\r
386      *\r
387      * The temporary fix is to always return E_OK here. But the reason for the bug needs to be investigated further.\r
388      */\r
389     //returnValue = E_NOT_OK;\r
390     returnValue = E_OK;\r
391   }\r
392   else\r
393   {\r
394     returnValue = E_OK;\r
395   }\r
396 #else\r
397   returnValue = E_OK;\r
398 #endif\r
399   return (returnValue);\r
400 }\r
401 #endif\r
402 \r
403 static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr)\r
404 {\r
405   Std_ReturnType returnValue;\r
406 \r
407 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
408   if (!(ADC_UNINIT == adcState))\r
409   {\r
410     /* Oops, already initialised. */\r
411     Det_ReportError(MODULE_ID_ADC,0,ADC_INIT_ID, ADC_E_ALREADY_INITIALIZED );\r
412     returnValue = E_NOT_OK;\r
413   }\r
414   else if (ConfigPtr == NULL)\r
415   {\r
416     /* Wrong config! */\r
417     Det_ReportError(MODULE_ID_ADC,0,ADC_INIT_ID, ADC_E_PARAM_CONFIG );\r
418     returnValue = E_NOT_OK;\r
419   }\r
420   else\r
421   {\r
422     /* Looks good!! */\r
423     returnValue = E_OK;\r
424   }\r
425 #else\r
426     returnValue = E_OK;\r
427 #endif\r
428   return (returnValue);\r
429 }\r
430 \r
431 static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group)\r
432 {\r
433   Std_ReturnType returnValue;\r
434 \r
435 #if ( ADC_DEV_ERROR_DETECT == STD_ON )\r
436   if (ADC_UNINIT == adcState)\r
437   {\r
438     /* Driver not initialised. */\r
439     Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_UNINIT );\r
440     returnValue = E_NOT_OK;\r
441   }\r
442   else if (group < AdcConfigPtr->nbrOfGroups)\r
443   {\r
444     /* ADC423 */\r
445     Det_ReportError(MODULE_ID_ADC,0,ADC_SETUPRESULTBUFFER_ID,ADC_E_PARAM_GROUP );\r
446     returnValue = E_NOT_OK;\r
447   }\r
448   else\r
449   {\r
450     /* Looks good!! */\r
451     returnValue = E_OK;\r
452   }\r
453 #else\r
454   returnValue = E_OK;\r
455 #endif\r
456   return (returnValue);\r
457 }\r
458 \r
459 \r