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
19 //#include "System.h"
\r
20 //#include "Modules.h"
\r
23 #include "stm32f10x_adc.h"
\r
24 #include "stm32f10x_dma.h"
\r
26 #if defined(USE_KERNEL)
\r
30 #include "Adc_Internal.h"
\r
32 /* Conversion result register for ADC1. */
\r
33 #define ADC1_DR_Address ((u32)0x4001244C)
\r
35 /* Function prototypes. */
\r
36 static void Adc_Group0ConversionComplete (void);
\r
39 static Adc_StateType adcState = ADC_UNINIT;
\r
41 /* Pointer to configuration structure. */
\r
42 static const Adc_ConfigType *AdcConfigPtr;
\r
45 #if (ADC_DEINIT_API == STD_ON)
\r
48 if (E_OK == Adc_CheckDeInit(adcState, AdcConfigPtr))
\r
50 DMA_DeInit(DMA1_Channel1);
\r
53 adcState = ADC_UNINIT;
\r
58 void Adc_Init (const Adc_ConfigType *ConfigPtr)
\r
60 Adc_GroupType group;
\r
62 ADC_InitTypeDef ADC_InitStructure;
\r
63 DMA_InitTypeDef DMA_InitStructure;
\r
65 ADC_TempSensorVrefintCmd(ENABLE);
\r
67 if (E_OK == Adc_CheckInit(adcState, ConfigPtr))
\r
69 /* First of all, store the location of the configuration data. */
\r
70 AdcConfigPtr = ConfigPtr;
\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
87 // Connect interrupt to correct isr
\r
88 ISR_INSTALL_ISR2( "DMA1", Adc_Group0ConversionComplete, DMA1_Channel1_IRQn, 6, 0 );
\r
90 /* Enable DMA1 channel1 */
\r
91 DMA_Cmd(DMA1_Channel1, ENABLE);
\r
93 /* Enable the DMA1 Channel1 Transfer complete interrupt */
\r
94 DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
\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
105 for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
\r
108 ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
111 /* Enable ADC1 DMA */
\r
112 ADC_DMACmd(ADC1, ENABLE);
\r
115 ADC_Cmd(ADC1, ENABLE);
\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
122 /* Start ADC1 calibaration */
\r
123 ADC_StartCalibration(ADC1);
\r
125 /* Check the end of ADC1 calibration */
\r
126 while(ADC_GetCalibrationStatus(ADC1)) ;
\r
128 /* Move on to INIT state. */
\r
129 adcState = ADC_INIT;
\r
133 Std_ReturnType Adc_SetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType *bufferPtr)
\r
135 Std_ReturnType returnValue;
\r
137 /* Check for development errors. */
\r
138 if (E_OK == Adc_CheckSetupResultBuffer (adcState, AdcConfigPtr, group))
\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
149 /* An error have been raised from Adc_CheckSetupResultBuffer(). */
\r
150 returnValue = E_NOT_OK;
\r
153 return (returnValue);
\r
156 #if (ADC_READ_GROUP_API == STD_ON)
\r
157 Std_ReturnType Adc_ReadGroup (Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)
\r
159 Std_ReturnType returnValue;
\r
160 Adc_ChannelType channel;
\r
162 if (E_OK == Adc_CheckReadGroup (adcState, AdcConfigPtr, group))
\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
168 /* ADC329, ADC331. */
\r
169 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
\r
170 returnValue = E_OK;
\r
172 /* Restart continous again after read */
\r
173 ADC_SoftwareStartConvCmd(ADC1, ENABLE);
\r
175 else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&
\r
176 (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))
\r
179 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
\r
181 returnValue = E_OK;
\r
186 returnValue = E_OK;
\r
189 if (E_OK == returnValue)
\r
191 /* Copy the result to application buffer. */
\r
192 for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)
\r
194 dataBufferPtr[channel] = AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr[channel];
\r
200 /* An error have been raised from Adc_CheckReadGroup(). */
\r
201 returnValue = E_NOT_OK;
\r
204 return (returnValue);
\r
208 static void Adc_Group0ConversionComplete (void)
\r
210 Adc_GroupDefType *groupPtr = NULL;
\r
212 /* ISR for DMA. Clear interrupt flag. */
\r
213 DMA_ClearFlag(DMA1_FLAG_TC1);
\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
218 if(AdcConfigPtr->groupConfigPtr[index].status->groupStatus == ADC_BUSY)
\r
220 groupPtr = (Adc_GroupDefType *)&AdcConfigPtr->groupConfigPtr[index];
\r
224 if(groupPtr != NULL)
\r
226 if(ADC_CONV_MODE_ONESHOT == groupPtr->conversionMode)
\r
228 groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;
\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
234 groupPtr->groupCallback();
\r
239 //Only single access supported so far for continous
\r
240 groupPtr->status->groupStatus = ADC_STREAM_COMPLETED;
\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
246 groupPtr->groupCallback();
\r
253 #if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)
\r
254 void Adc_StartGroupConversion (Adc_GroupType group)
\r
256 /* Run development error check. */
\r
257 if (E_OK == Adc_CheckStartGroupConversion (adcState, AdcConfigPtr, group))
\r
259 Adc_ChannelType channel;
\r
260 Adc_ChannelType channelId;
\r
262 /* Configure the channel queue. */
\r
263 ADC1->SQR1 = (AdcConfigPtr->groupConfigPtr[group].numberOfChannels -1) << 20;
\r
266 /* Loop through all channels and make the command queue. */
\r
267 for (channel = 0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)
\r
269 /* Get physical channel. */
\r
270 channelId = AdcConfigPtr->groupConfigPtr[group].channelList[channel];
\r
272 /* Configure channel as regular. */
\r
273 ADC_RegularChannelConfig(ADC1, channelId, channel+1,
\r
274 AdcConfigPtr->channelConfigPtr [channel].adcChannelConvTime);
\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
282 ADC1->CR2 = ADC1->CR2 | (1<<1);
\r
285 ADC_SoftwareStartConvCmd(ADC1, ENABLE);
\r
286 /* Set group state to BUSY. */
\r
287 AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
\r
291 /* Error have been set within Adc_CheckStartGroupConversion(). */
\r
295 void Adc_StopGroupConversion (Adc_GroupType group)
\r
297 /* Run development error check. */
\r
298 if (E_OK == Adc_CheckStopGroupConversion (adcState, AdcConfigPtr, group))
\r
300 ADC_SoftwareStartConvCmd(ADC1, DISABLE);
\r
304 /* Error have been set within Adc_CheckStartGroupConversion(). */
\r
309 #if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
\r
310 void Adc_EnableGroupNotification (Adc_GroupType group)
\r
312 Adc_EnableInternalGroupNotification(adcState, AdcConfigPtr, group);
\r
315 void Adc_DisableGroupNotification (Adc_GroupType group)
\r
317 Adc_InternalDisableGroupNotification(adcState, AdcConfigPtr, group);
\r
321 Adc_StatusType Adc_GetGroupStatus (Adc_GroupType group)
\r
323 return Adc_InternalGetGroupStatus(adcState, AdcConfigPtr, group);
\r