Version 0.06
[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 True 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  * NeuG 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_SMPR1_SMP_AN10(n)   ((n) << 0)
39 #define ADC_SMPR1_SMP_AN11(n)   ((n) << 3)
40
41 #define ADC_SMPR2_SMP_AN0(n)    ((n) << 0)
42 #define ADC_SMPR2_SMP_AN1(n)    ((n) << 3)
43 #define ADC_SMPR2_SMP_AN2(n)    ((n) << 6)
44 #define ADC_SMPR2_SMP_AN9(n)    ((n) << 27)
45
46 #define ADC_SQR1_NUM_CH(n)      (((n) - 1) << 20)
47
48 #define ADC_SQR3_SQ1_N(n)       ((n) << 0)
49 #define ADC_SQR3_SQ2_N(n)       ((n) << 5)
50 #define ADC_SQR3_SQ3_N(n)       ((n) << 10)
51 #define ADC_SQR3_SQ4_N(n)       ((n) << 15)
52
53 #define ADC_SAMPLE_1P5          0
54
55 #define ADC_CHANNEL_IN0         0
56 #define ADC_CHANNEL_IN1         1
57 #define ADC_CHANNEL_IN2         2
58 #define ADC_CHANNEL_IN9         9
59 #define ADC_CHANNEL_IN10        10
60 #define ADC_CHANNEL_IN11        11
61 #define ADC_CHANNEL_SENSOR      16
62 #define ADC_CHANNEL_VREFINT     17
63
64 #define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
65 #define DELIBARATELY_DO_IT_WRONG_START_STOP
66
67 #ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
68 #define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
69 #define ADC_SAMPLE_SENSOR ADC_SAMPLE_1P5
70 #else
71 #define ADC_SAMPLE_VREF ADC_SAMPLE_239P5
72 #define ADC_SAMPLE_SENSOR ADC_SAMPLE_239P5
73 #endif
74
75 #define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
76 #define NEUG_DMA_MODE_SAMPLE                                            \
77   (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                      \
78      | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD                \
79      | STM32_DMA_CR_MINC       | STM32_DMA_CR_TCIE                      \
80      | STM32_DMA_CR_TEIE)
81
82 #define NEUG_DMA_MODE_CRC32                                             \
83   (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)                      \
84      | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD                \
85      | STM32_DMA_CR_TCIE       | STM32_DMA_CR_TEIE)
86
87 #define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF)     \
88                               | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
89 #define NEUG_ADC_SETTING1_SMPR2 0
90 #define NEUG_ADC_SETTING1_SQR3  ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)     \
91                               | ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR)      \
92                               | ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR)      \
93                               | ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)     
94 #define NEUG_ADC_SETTING1_NUM_CHANNELS 4
95
96 #if !defined(NEUG_ADC_SETTING2_SMPR1)
97 #define NEUG_ADC_SETTING2_SMPR1 0
98 #define NEUG_ADC_SETTING2_SMPR2 ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)    \
99                               | ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
100 #define NEUG_ADC_SETTING2_SQR3  ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)      \
101                               | ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1)
102 #define NEUG_ADC_SETTING2_NUM_CHANNELS 2
103 #endif
104
105
106 /*
107  * Do calibration for both of ADCs.
108  */
109 void adc_init (void)
110 {
111   chSysLock ();
112   rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
113   ADC1->CR1 = 0;
114   ADC1->CR2 = ADC_CR2_ADON;
115   ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
116   while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
117     ;
118   ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
119   while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
120     ;
121   ADC1->CR2 = 0;
122
123   ADC2->CR1 = 0;
124   ADC2->CR2 = ADC_CR2_ADON;
125   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
126   while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
127     ;
128   ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
129   while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
130     ;
131   ADC2->CR2 = 0;
132   rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
133   chSysUnlock ();
134 }
135
136 static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags);
137
138 void adc_start (void)
139 {
140   dmaStreamAllocate (NEUG_DMA_CHANNEL, STM32_ADC_ADC1_IRQ_PRIORITY,
141                      adc_lld_serve_rx_interrupt, NULL);
142   dmaStreamSetPeripheral (NEUG_DMA_CHANNEL, &ADC1->DR);
143
144   chSysLock ();
145
146   rccEnableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
147
148   ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
149                | ADC_CR1_SCAN);
150   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
151                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
152   ADC1->SMPR1 = NEUG_ADC_SETTING1_SMPR1;
153   ADC1->SMPR2 = NEUG_ADC_SETTING1_SMPR2;
154   ADC1->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING1_NUM_CHANNELS);
155   ADC1->SQR2 = 0;
156   ADC1->SQR3 = NEUG_ADC_SETTING1_SQR3;
157
158   ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
159                | ADC_CR1_SCAN);
160   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
161   ADC2->SMPR1 = NEUG_ADC_SETTING2_SMPR1;
162   ADC2->SMPR2 = NEUG_ADC_SETTING2_SMPR2;
163   ADC2->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING2_NUM_CHANNELS);
164   ADC2->SQR2 = 0;
165   ADC2->SQR3 = NEUG_ADC_SETTING2_SQR3;
166
167 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
168   ADC2->CR2 = 0;
169   ADC1->CR2 = 0;
170 #endif
171
172   chSysUnlock ();
173 }
174
175 static int adc_mode;
176 static uint32_t *adc_ptr;
177 static int adc_size;
178
179 static void adc_start_conversion_internal (void)
180 {
181 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
182   /* Power on */
183   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
184   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
185                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
186   /* Start conversion.  tSTAB is 1uS, but we don't follow the spec.  */
187   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
188   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
189                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
190 #else
191   ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
192   ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
193                | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
194 #endif
195 }
196
197 void adc_start_conversion (int mode, uint32_t *p, int size)
198 {
199   adc_mode = mode;
200   adc_ptr = p;
201   adc_size = size;
202
203  if (mode == ADC_SAMPLE_MODE)
204     {
205       dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, p);
206       dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, size / 4);
207       dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_SAMPLE);
208       dmaStreamEnable (NEUG_DMA_CHANNEL);
209     }
210   else
211     {
212       dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
213       dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
214       dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
215       dmaStreamEnable (NEUG_DMA_CHANNEL);
216     }
217
218  adc_start_conversion_internal ();
219 }
220
221
222 static void adc_stop_conversion (void)
223 {
224   dmaStreamDisable (NEUG_DMA_CHANNEL);
225 #ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
226   ADC1->CR2 = 0;
227   ADC2->CR2 = 0;
228 #else
229   ADC2->CR2 &= ~ADC_CR2_CONT;
230   ADC1->CR2 &= ~ADC_CR2_CONT;
231 #endif
232 }
233
234 void adc_stop (void)
235 {
236   ADC1->CR1 = 0;
237   ADC1->CR2 = 0;
238
239   ADC2->CR1 = 0;
240   ADC2->CR2 = 0;
241
242   dmaStreamRelease (NEUG_DMA_CHANNEL);
243   rccDisableAPB2 (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN, FALSE);
244 }
245
246
247 static void adc_lld_serve_rx_interrupt (void *arg, uint32_t flags)
248 {
249   (void)arg;
250
251   if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
252     {
253       /* Should never happened.  If any, it's coding error. */
254       /* Access an unmapped address space or alignment violation.  */
255       adc_stop_conversion ();
256     }
257   else
258     {
259       if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
260         {
261           adc_stop_conversion ();
262
263           if (adc_mode != ADC_SAMPLE_MODE)
264             {
265               adc_size -= 4;
266               *adc_ptr++ = CRC->DR;
267
268               if (adc_size > 0)
269                 {
270                   dmaStreamSetMemory0 (NEUG_DMA_CHANNEL, &CRC->DR);
271                   dmaStreamSetTransactionSize (NEUG_DMA_CHANNEL, NEUG_CRC32_COUNTS);
272                   dmaStreamSetMode (NEUG_DMA_CHANNEL, NEUG_DMA_MODE_CRC32);
273                   dmaStreamEnable (NEUG_DMA_CHANNEL);
274
275                   adc_start_conversion_internal ();
276                 }
277             }
278
279           if (adc_mode == ADC_SAMPLE_MODE || adc_size <= 0)
280             {
281               chSysLockFromIsr();
282               if (rng_thread)
283                 chEvtSignalFlagsI (rng_thread, ADC_DATA_AVAILABLE);
284               chSysUnlockFromIsr();
285             }
286         }
287     }
288 }