4232456d856d1da13e2d186fe7c6b1c3e93e2000
[gnuk/neug.git] / src / adc_stm32f103.c
1 /*
2  * adc_stm32f103.c - ADC driver for STM32F103
3  *
4  * Copyright (C) 2011, 2012 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of NeuG, a Random Number Generator
8  * implementation based on quantization error of ADC (for STM32F103).
9  *
10  * NeuG is free software: you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "ch.h"
26 #include "hal.h"
27 #include "neug.h"
28 #include "adc.h"
29
30 #define NEUG_CRC32_COUNTS 4
31
32 #define STM32_ADC_ADC1_DMA_PRIORITY         2
33 #define STM32_ADC_ADC1_IRQ_PRIORITY         5
34
35 #define ADC_SMPR1_SMP_VREF(n)   ((n) << 21)
36 #define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18)
37
38 #define ADC_SMPR2_SMP_AN0(n)    ((n) << 0)
39 #define ADC_SMPR2_SMP_AN1(n)    ((n) << 3)
40
41 #define ADC_SQR1_NUM_CH(n)      (((n) - 1) << 20)
42
43 #define ADC_SQR3_SQ1_N(n)       ((n) << 0)
44 #define ADC_SQR3_SQ2_N(n)       ((n) << 5)
45 #define ADC_SQR3_SQ3_N(n)       ((n) << 10)
46 #define ADC_SQR3_SQ4_N(n)       ((n) << 15)
47
48 #define ADC_SAMPLE_1P5          0
49
50 #define ADC_CHANNEL_IN0         0
51 #define ADC_CHANNEL_IN1         1
52 #define ADC_CHANNEL_SENSOR      16
53 #define ADC_CHANNEL_VREFINT     17
54
55 #define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
56 #define DELIBARATELY_DO_IT_WRONG_START_STOP
57
58 #ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
59 #define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
60 #define ADC_SAMPLE_SENSOR ADC_SAMPLE_1P5
61 #else
62 #define ADC_SAMPLE_VREF ADC_SAMPLE_239P5
63 #define ADC_SAMPLE_SENSOR ADC_SAMPLE_239P5
64 #endif
65
66 #define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
67 #define NEUG_DMA_MODE_SAMPLE                                            \
68   (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                      \
69      | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD                \
70      | STM32_DMA_CR_MINC       | STM32_DMA_CR_TCIE                      \
71      | STM32_DMA_CR_TEIE)
72
73 #define NEUG_DMA_MODE_CRC32                                             \
74   (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                      \
75      | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD                \
76      | STM32_DMA_CR_TCIE       | STM32_DMA_CR_TEIE)
77
78 #define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF)     \
79                               | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
80 #define NEUG_ADC_SETTING1_SMPR2 0
81 #define NEUG_ADC_SETTING1_SQR3  ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)     \
82                               | ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR)      \
83                               | ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR)      \
84                               | ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)     
85 #define NEUG_ADC_SETTING1_NUM_CHANNELS 4
86
87 #if !defined(NEUG_ADC_SETTING2_SMPR1)
88 #define NEUG_ADC_SETTING2_SMPR1 0
89 #define NEUG_ADC_SETTING2_SMPR2 ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)    \
90                               | ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
91 #define NEUG_ADC_SETTING2_SQR3  ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)      \
92                               | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1)
93 #define NEUG_ADC_SETTING2_NUM_CHANNELS 2
94 #endif
95
96
97 /*
98  * Do calibration for both of ADCs.
99  */
100 void adc_init (void)
101 {
102   chSysLock ();
103   rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
104   ADC1->CR1 = 0;
105   ADC1->CR2 = ADC_CR2_ADON;
106   ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
107   while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
108     ;
109   ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
110   while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
111     ;
112   ADC1->CR2 = 0;
113
114   ADC2->CR1 = 0;
115   ADC2->CR2 = ADC_CR2_ADON;
116   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
117   while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
118     ;
119   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
120   while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
121     ;
122   ADC2->CR2 = 0;
123   rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
124   chSysUnlock ();
125 }
126
127 static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags);
128
129 void adc_start (void)
130 {
131   dmaStreamAllocate (NEUG_DMA_CHANNEL, STM32_ADC_ADC1_IRQ_PRIORITY,
132                      adc_lld_serve_rx_interrupt, NULL);
133   dmaStreamSetPeripheral (NEUG_DMA_CHANNEL, &ADC1->DR);
134
135   chSysLock ();
136
137   rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
138
139   ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
140                | ADC_CR1_SCAN);
141   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
142                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
143   ADC1->SMPR1 = NEUG_ADC_SETTING1_SMPR1;
144   ADC1->SMPR2 = NEUG_ADC_SETTING1_SMPR2;
145   ADC1->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING1_NUM_CHANNELS);
146   ADC1->SQR2 = 0;
147   ADC1->SQR3 = NEUG_ADC_SETTING1_SQR3;
148
149   ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
150                | ADC_CR1_SCAN);
151   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
152   ADC2->SMPR1 = NEUG_ADC_SETTING2_SMPR1;
153   ADC2->SMPR2 = NEUG_ADC_SETTING2_SMPR2;
154   ADC2->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING2_NUM_CHANNELS);
155   ADC2->SQR2 = 0;
156   ADC2->SQR3 = NEUG_ADC_SETTING2_SQR3;
157
158 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
159   ADC2->CR2 = 0;
160   ADC1->CR2 = 0;
161 #endif
162
163   chSysUnlock ();
164 }
165
166 static int adc_mode;
167 static uint32_t *adc_ptr;
168 static int adc_size;
169
170 static void adc_start_conversion_internal (void)
171 {
172 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
173   /* Power on */
174   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
175   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
176                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
177   /* Start conversion.  tSTAB is 1uS, but we don't follow the spec.  */
178   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
179   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
180                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
181 #else
182   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
183   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
184                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
185 #endif
186 }
187
188 void adc_start_conversion (int mode, uint32_t *p, int size)
189 {
190   adc_mode = mode;
191   adc_ptr = p;
192   adc_size = size;
193
194  if (mode == ADC_SAMPLE_MODE)
195     {
196       dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, p);
197       dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, size / 4);
198       dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_SAMPLE);
199       dmaStreamEnable (NEUG_DMA_CHANNEL);
200     }
201   else
202     {
203       dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
204       dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
205       dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
206       dmaStreamEnable (NEUG_DMA_CHANNEL);
207     }
208
209  adc_start_conversion_internal ();
210 }
211
212
213 static void adc_stop_conversion (void)
214 {
215   dmaStreamDisable (NEUG_DMA_CHANNEL);
216 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
217   ADC1->CR2 = 0;
218   ADC2->CR2 = 0;
219 #else
220   ADC2->CR2 &= ~ADC_CR2_CONT;
221   ADC1->CR2 &= ~ADC_CR2_CONT;
222 #endif
223 }
224
225 void adc_stop (void)
226 {
227   ADC1->CR1 = 0;
228   ADC1->CR2 = 0;
229
230   ADC2->CR1 = 0;
231   ADC2->CR2 = 0;
232
233   dmaStreamRelease (NEUG_DMA_CHANNEL);
234   rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
235 }
236
237
238 static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags)
239 {
240   (void)arg;
241
242   if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
243     {
244       /* Should never happened.  If any, it's coding error. */
245       /* Access an unmapped address space or alignment violation.  */
246       adc_stop_conversion ();
247     }
248   else
249     {
250       if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
251         {
252           adc_stop_conversion ();
253
254           if (adc_mode != ADC_SAMPLE_MODE)
255             {
256               adc_size -= 4;
257               *adc_ptr++ = CRC->DR;
258
259               if (adc_size > 0)
260                 {
261                   dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
262                   dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
263                   dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
264                   dmaStreamEnable (NEUG_DMA_CHANNEL);
265
266                   adc_start_conversion_internal ();
267                 }
268             }
269
270           if (adc_mode == ADC_SAMPLE_MODE || adc_size <= 0)
271             {
272               chSysLockFromIsr();
273               if (rng_thread)
274                 chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE);
275               chSysUnlockFromIsr();
276             }
277         }
278     }
279 }