]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Adc.c
0559027963f725b807b08e8489e8b37b5a6446e1
[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 #include "Adc_Internal.h"\r
31 \r
32 /* Conversion result register for ADC1. */\r
33 #define ADC1_DR_Address    ((u32)0x4001244C)\r
34 \r
35 /* Function prototypes. */\r
36 static void Adc_Group0ConversionComplete (void);\r
37 \r
38 \r
39 static Adc_StateType adcState = ADC_UNINIT;\r
40 \r
41 /* Pointer to configuration structure. */\r
42 static const Adc_ConfigType *AdcConfigPtr;\r
43 \r
44 \r
45 #if (ADC_DEINIT_API == STD_ON)\r
46 void Adc_DeInit ()\r
47 {\r
48         if (E_OK == Adc_CheckDeInit(adcState, AdcConfigPtr))\r
49         {\r
50           DMA_DeInit(DMA1_Channel1);\r
51           ADC_DeInit(ADC1);\r
52 \r
53           adcState = ADC_UNINIT;\r
54         }\r
55 }\r
56 #endif\r
57 \r
58 void Adc_Init (const Adc_ConfigType *ConfigPtr)\r
59 {\r
60   Adc_GroupType group;\r
61 \r
62   ADC_InitTypeDef ADC_InitStructure;\r
63   DMA_InitTypeDef DMA_InitStructure;\r
64 \r
65   ADC_TempSensorVrefintCmd(ENABLE);\r
66 \r
67   if (E_OK == Adc_CheckInit(adcState, ConfigPtr))\r
68   {\r
69     /* First of all, store the location of the configuration data. */\r
70     AdcConfigPtr = ConfigPtr;\r
71 \r
72     /* DMA1 channel1 configuration ---------------------------------------------*/\r
73     DMA_DeInit(DMA1_Channel1);\r
74     DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;\r
75     DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ConfigPtr->groupConfigPtr->resultBuffer;\r
76     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;\r
77     DMA_InitStructure.DMA_BufferSize = ConfigPtr->groupConfigPtr->numberOfChannels;\r
78     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;\r
79     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;\r
80     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;\r
81     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;\r
82     DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;\r
83     DMA_InitStructure.DMA_Priority = DMA_Priority_High;\r
84     DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;\r
85     DMA_Init(DMA1_Channel1, &DMA_InitStructure);\r
86 \r
87       // Connect interrupt to correct isr\r
88         ISR_INSTALL_ISR2( "DMA1", Adc_Group0ConversionComplete, DMA1_Channel1_IRQn, 6, 0 );\r
89 \r
90     /* Enable DMA1 channel1 */\r
91     DMA_Cmd(DMA1_Channel1, ENABLE);\r
92 \r
93     /* Enable the DMA1 Channel1 Transfer complete interrupt */\r
94     DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);\r
95 \r
96     /* ADC1 configuration ------------------------------------------------------*/\r
97     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;\r
98     ADC_InitStructure.ADC_ScanConvMode = ENABLE;\r
99     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;\r
100     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;\r
101     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;\r
102     ADC_InitStructure.ADC_NbrOfChannel = ConfigPtr->groupConfigPtr->numberOfChannels;\r
103     ADC_Init(ADC1, &ADC_InitStructure);\r
104 \r
105     for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)\r
106     {\r
107       /* ADC307. */\r
108       ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
109     }\r
110 \r
111     /* Enable ADC1 DMA */\r
112     ADC_DMACmd(ADC1, ENABLE);\r
113 \r
114     /* Enable ADC1 */\r
115     ADC_Cmd(ADC1, ENABLE);\r
116 \r
117     /* Enable ADC1 reset calibaration register */\r
118     ADC_ResetCalibration(ADC1);\r
119     /* Check the end of ADC1 reset calibration register */\r
120     while(ADC_GetResetCalibrationStatus(ADC1)) ;\r
121 \r
122     /* Start ADC1 calibaration */\r
123     ADC_StartCalibration(ADC1);\r
124 \r
125     /* Check the end of ADC1 calibration */\r
126     while(ADC_GetCalibrationStatus(ADC1)) ;\r
127 \r
128     /* Move on to INIT state. */\r
129     adcState = ADC_INIT;\r
130   }\r
131 }\r
132 \r
133 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)\r
134 {\r
135   Std_ReturnType returnValue;\r
136 \r
137   /* Check for development errors. */\r
138   if (E_OK == Adc_CheckSetupResultBuffer (adcState, AdcConfigPtr, group))\r
139   {\r
140     AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = bufferPtr;\r
141     DMA_Cmd(DMA1_Channel1, DISABLE);\r
142     DMA1_Channel1->CMAR = (u32)AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr;\r
143     DMA1_Channel1->CNDTR = AdcConfigPtr->groupConfigPtr[group].numberOfChannels;\r
144     DMA_Cmd(DMA1_Channel1, ENABLE);\r
145     returnValue = E_OK;\r
146   }\r
147   else\r
148   {\r
149     /* An error have been raised from Adc_CheckSetupResultBuffer(). */\r
150     returnValue = E_NOT_OK;\r
151   }\r
152 \r
153   return (returnValue);\r
154 }\r
155 \r
156 #if (ADC_READ_GROUP_API == STD_ON)\r
157 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)\r
158 {\r
159   Std_ReturnType returnValue;\r
160   Adc_ChannelType channel;\r
161 \r
162   if (E_OK == Adc_CheckReadGroup (adcState, AdcConfigPtr, group))\r
163   {\r
164     if ((ADC_CONV_MODE_CONTINUOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
165          ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||\r
166           (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))\r
167     {\r
168       /* ADC329, ADC331. */\r
169       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
170       returnValue = E_OK;\r
171 \r
172       /* Restart continous again after read */\r
173       ADC_SoftwareStartConvCmd(ADC1, ENABLE);\r
174     }\r
175     else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&\r
176              (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))\r
177     {\r
178       /* ADC330. */\r
179       AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;\r
180 \r
181       returnValue = E_OK;\r
182     }\r
183     else\r
184     {\r
185       /* Keep status. */\r
186       returnValue = E_OK;\r
187     }\r
188 \r
189     if (E_OK == returnValue)\r
190     {\r
191       /* Copy the result to application buffer. */\r
192       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
193       {\r
194         dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr[channel];\r
195       }\r
196     }\r
197   }\r
198   else\r
199   {\r
200     /* An error have been raised from Adc_CheckReadGroup(). */\r
201     returnValue = E_NOT_OK;\r
202   }\r
203 \r
204   return (returnValue);\r
205 }\r
206 #endif\r
207 \r
208 static void Adc_Group0ConversionComplete (void)\r
209 {\r
210   Adc_GroupDefType *groupPtr = NULL;\r
211 \r
212   /* ISR for DMA. Clear interrupt flag.  */\r
213   DMA_ClearFlag(DMA1_FLAG_TC1);\r
214 \r
215   // Check which group is busy, only one is allowed to be busy at a time in a hw unit\r
216   for (uint8 index = 0; index < ADC_NBR_OF_GROUPS; index++)\r
217   {\r
218           if(AdcConfigPtr->groupConfigPtr[index].status->groupStatus == ADC_BUSY)\r
219           {\r
220                   groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[index];\r
221                   break;\r
222           }\r
223   }\r
224   if(groupPtr != NULL)\r
225   {\r
226           if(ADC_CONV_MODE_ONESHOT == groupPtr->conversionMode)\r
227           {\r
228                   groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;\r
229 \r
230                   /* Call notification if enabled. */\r
231                 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
232                   if (groupPtr->status->notifictionEnable && groupPtr->groupCallback != NULL)\r
233                   {\r
234                           groupPtr->groupCallback();\r
235                   }\r
236                 #endif\r
237           }\r
238           else{\r
239                   //Only single access supported so far for continous\r
240                   groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;\r
241 \r
242                   /* Call notification if enabled. */\r
243                 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
244                   if (groupPtr->status->notifictionEnable && groupPtr->groupCallback != NULL)\r
245                   {\r
246                           groupPtr->groupCallback();\r
247                   }\r
248                 #endif\r
249           }\r
250   }\r
251 }\r
252 \r
253 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)\r
254 void Adc_StartGroupConversion (Adc_GroupType group)\r
255 {\r
256   /* Run development error check. */\r
257   if (E_OK == Adc_CheckStartGroupConversion (adcState, AdcConfigPtr, group))\r
258   {\r
259           Adc_ChannelType channel;\r
260           Adc_ChannelType channelId;\r
261 \r
262           /* Configure the channel queue. */\r
263         ADC1->SQR1 = (AdcConfigPtr->groupConfigPtr[group].numberOfChannels -1) << 20;\r
264         ADC1->SQR2 = 0;\r
265         ADC1->SQR3 = 0;\r
266       /* Loop through all channels and make the command queue. */\r
267       for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)\r
268       {\r
269         /* Get physical channel. */\r
270         channelId = AdcConfigPtr->groupConfigPtr[group].channelList[channel];\r
271 \r
272         /* Configure channel as regular. */\r
273         ADC_RegularChannelConfig(ADC1, channelId, channel+1,\r
274                         AdcConfigPtr->channelConfigPtr [channel].adcChannelConvTime);\r
275 \r
276       }\r
277 \r
278     /* Set conversion mode. No need we run always in single shot and handle continous ourselves */\r
279 /*      if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT){\r
280                 ADC1->CR2 = ADC1->CR2 & ~(1<<1);\r
281         }else{\r
282                 ADC1->CR2 = ADC1->CR2 | (1<<1);\r
283         }*/\r
284 \r
285     ADC_SoftwareStartConvCmd(ADC1, ENABLE);\r
286     /* Set group state to BUSY. */\r
287     AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;\r
288   }\r
289   else\r
290   {\r
291     /* Error have been set within Adc_CheckStartGroupConversion(). */\r
292   }\r
293 }\r
294 \r
295 void Adc_StopGroupConversion (Adc_GroupType group)\r
296 {\r
297   /* Run development error check. */\r
298   if (E_OK == Adc_CheckStopGroupConversion (adcState, AdcConfigPtr, group))\r
299   {\r
300             ADC_SoftwareStartConvCmd(ADC1, DISABLE);\r
301   }\r
302   else\r
303   {\r
304         /* Error have been set within Adc_CheckStartGroupConversion(). */\r
305   }\r
306 }\r
307 #endif\r
308 \r
309 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)\r
310 void Adc_EnableGroupNotification (Adc_GroupType group)\r
311 {\r
312         Adc_EnableInternalGroupNotification(adcState, AdcConfigPtr, group);\r
313 }\r
314 \r
315 void Adc_DisableGroupNotification (Adc_GroupType group)\r
316 {\r
317         Adc_InternalDisableGroupNotification(adcState, AdcConfigPtr, group);\r
318 }\r
319 #endif\r
320 \r
321 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)\r
322 {\r
323         return Adc_InternalGetGroupStatus(adcState, AdcConfigPtr, group);\r
324 }\r